[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-28 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added a subscriber: cfe-commits.

Added support of creating a hardlink from one file to another file.
After a hardlink is added between two files, both file will have the same:

1. UniqueID (inode)
2. Size
3. Buffer

This will bring replay of compilation closer to the actual compilation. There 
are instances where clang checks for the UniqueID of the file/header to be 
loaded which leads to a different behavior during replay as all files have 
different UniqueIDs.


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -695,6 +696,20 @@
   InMemoryFileSystemTest()
   : FS(/*UseNormalizedPaths=*/false),
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
+
+public:
+  void ExpectHardLink(Twine From, Twine To) {
+auto OpenedFrom = FS.openFileForRead(From);
+ASSERT_FALSE(OpenedFrom.getError());
+auto OpenedTo = FS.openFileForRead(To);
+ASSERT_FALSE(OpenedTo.getError());
+ASSERT_EQ((*OpenedFrom)->status()->getSize(),
+  (*OpenedTo)->status()->getSize());
+ASSERT_EQ((*OpenedFrom)->status()->getUniqueID(),
+  (*OpenedTo)->status()->getUniqueID());
+ASSERT_EQ((*OpenedFrom)->getBuffer(From)->get()->getBuffer(),
+  (*OpenedTo)->getBuffer(To)->get()->getBuffer());
+  }
 };
 
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
@@ -958,6 +973,96 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkWithToFileNotAddedBefore) {
+  std::pair From = {"/path/to/FROM/file",
+"content of FROM file"};
+  std::pair To = {"/path/to/TO/file",
+  "content of TO file"};
+  FS.addFile(From.first, 0, MemoryBuffer::getMemBuffer(From.second));
+  FS.addHardlink(From.first, To.first, /*CopyBuffer=*/true);
+  ExpectHardLink(From.first, To.first);
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkWithToFileThatWasAlreadyAdded) {
+  std::pair From = {"/path/to/FROM/file",
+"content of FROM file"};
+  std::pair To = {"/path/to/TO/file",
+  "content of TO file"};
+  FS.addFile(From.first, 0, MemoryBuffer::getMemBuffer(From.second));
+  FS.addFile(To.first, 0, MemoryBuffer::getMemBuffer(To.second));
+  FS.addHardlink(From.first, To.first, /*CopyBuffer=*/true);
+  ExpectHardLink(From.first, To.first);
+}
+
+TEST_F(InMemoryFileSystemTest, AddMoreThanOneHardLinkToSameFile) {
+  std::pair From = {"/path/to/FROM/file",
+"content of FROM file"};
+  std::pair To = {"/path/to/TO/file",
+  "content of TO file"};
+  FS.addFile(From.first, 0, MemoryBuffer::getMemBuffer(From.second));
+  FS.addFile(To.first, 0, MemoryBuffer::getMemBuffer(To.second));
+  for (int i = 0; i < 5; ++i)
+FS.addHardlink(From.first, To.first, /*CopyBuffer=*/true);
+  ExpectHardLink(From.first, To.first);
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAlreadyLinkedFiles) {
+  std::pair From = {"/path/to/FROM/file",
+  "content of FROM file"};
+  FS.addFile(From.first, 0, MemoryBuffer::getMemBuffer(From.second.data()));
+  std::vector> ToFiles;
+  ToFiles.reserve(5);
+  for (int i = 0; i < 5; ++i) {
+ToFiles.push_back(
+{"/path/to/TO/file_" + std::to_string(i), "content of to file"});
+  }
+  for (const auto &to : ToFiles) {
+FS.addFile(to.first.data(), 0,
+   MemoryBuffer::getMemBuffer(to.second.data()));
+  }
+  for (int i = 1; i < 5; ++i) {
+FS.addHardlink(ToFiles[i - 1].first.data(), ToFiles[i].first.data(),
+   /*CopyBuffer=*/false);
+  }
+  FS.addHardlink(From.first, ToFiles[0].first.data(), /*CopyBuffer=*/true);
+  for (const auto &to : ToFiles) {
+ExpectHardLink(From.first, to.first.data());
+  }
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkBetweenTwoGroups) {
+  std::vector> FileGroup1, FileGroup2;
+  for (int i = 0; i < 5; ++i) {
+string str_i = std::to_string(i);
+FileGroup1.push_back(
+{"/path/to/group/1/file_" + str_i, "group1, file =" + str_i});
+FileGroup2.push_back(
+{"/path/to/group/2/file_" + str_i, "group2, file =" + str_i});
+  }
+  // Create files for both groups.
+  for (int i = 0; i < 5; ++i) {
+FS.addFile(FileGroup1[i].first.data(), 0,
+   MemoryBuffer::getMemBuffer(FileGroup1[i].second.data()));
+FS.addFile(FileGroup2[i].first.data()

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-29 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163128.
usaxena95 added a comment.

  Created InMemoryHardLink Class which can handle the resolved InMemoryFile


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -695,6 +696,22 @@
   InMemoryFileSystemTest()
   : FS(/*UseNormalizedPaths=*/false),
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
+
+public:
+  void ExpectHardLink(Twine From, Twine To, const string& ExpectedBuffer) {
+auto OpenedFrom = FS.openFileForRead(From);
+ASSERT_FALSE(OpenedFrom.getError());
+auto OpenedTo = FS.openFileForRead(To);
+ASSERT_FALSE(OpenedTo.getError());
+ASSERT_EQ((*OpenedFrom)->status()->getSize(),
+  (*OpenedTo)->status()->getSize());
+ASSERT_EQ((*OpenedFrom)->status()->getUniqueID(),
+  (*OpenedTo)->status()->getUniqueID());
+ASSERT_EQ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data(),
+  (*OpenedTo)->getBuffer(To)->get()->getBuffer().data());
+ASSERT_EQ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data(),
+  ExpectedBuffer);
+  }
 };
 
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
@@ -958,6 +975,84 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  std::pair From = {"/path/to/FROM/file",
+"content of FROM file"};
+  std::pair To = {"/path/to/TO/file",
+  "content of TO file"};
+  FS.addFile(To.first, 0, MemoryBuffer::getMemBuffer(To.second));
+  EXPECT_TRUE(FS.addHardLink(From.first, To.first));
+  ExpectHardLink(From.first, To.first, To.second.data());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef content = "content of target file";
+  Twine link0 = "/path/to/0/link";
+  Twine link1 = "/path/to/1/link";
+  Twine link2 = "/path/to/2/link";
+  Twine target = "/path/to/target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link2, target));
+  EXPECT_TRUE(FS.addHardLink(link1, link2));
+  EXPECT_TRUE(FS.addHardLink(link0, link1));
+  ExpectHardLink(link0, target, content.data());
+  ExpectHardLink(link1, target, content.data());
+  ExpectHardLink(link2, target, content.data());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  Twine link = "/path/to/link";
+  StringRef content_link = "content of link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content_link));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_TRUE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  StringRef link_content = "different content of link";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(link_content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine link = "/path/to/link";
+  Twine dummy_file = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(dummy_file, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(link, dir));
+}
+
 // NOTE: in the tests below, we use '//root/' as our root directory, since it is
 // 

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-29 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 marked 8 inline comments as done.
usaxena95 added a comment.

Applied the suggested changes. Added InMemoryHardLink as a subclass of 
InMemoryNode.  Modified the tests accordingly.


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-30 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 marked 7 inline comments as done.
usaxena95 added a comment.

> Could we try removing Status from the base class and move it into 
> `InMemoryFile` and `InMemoryDir`?

Moved the Stat and **getStatus** into the subclasses. User of **getStatus** now 
calls **getStatus** of individual subclasses.




Comment at: lib/Basic/VirtualFileSystem.cpp:526
+  InMemoryNode *ResolvedNode;
+  StringRef Name;
+

ilya-biryukov wrote:
> Can we get away without storing `Name`? `toString()` can just say `"hard link 
> to "  + ResolveNode->toString()`
Yeah we can do that. It is just for debug purpose only.



Comment at: lib/Basic/VirtualFileSystem.cpp:529
+public:
+  InMemoryHardLink(Status Stat, InMemoryNode *ResolvedNode)
+  : InMemoryNode(std::move(Stat), IME_HARD_LINK),

ilya-biryukov wrote:
> ilya-biryukov wrote:
> > Why do we need the Stat?
> > We can get it from `ResolveNode` if we want to store a copy. Any reason why 
> > it would be different?
> ResolveNode can't be `null`, right? Maybe use a reference instead?
> Also, maybe make it const?
Changed it to reference. Can't make it const as the there it is involved in 
methods that are non const (like getResolvedFile returns a pointer, getBuffer 
is not const)



Comment at: lib/Basic/VirtualFileSystem.cpp:535
+  InMemoryNode *getResolvedNode() { return ResolvedNode; }
+  llvm::MemoryBuffer *getBuffer() {
+return static_cast(ResolvedNode)->getBuffer();

ilya-biryukov wrote:
> Could we inline `getBuffer` and `getStatus`? Having the client code that's 
> explicit about resolving the references seems like a good idea.
Removed these methods. Moved the logic to client code.


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-30 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163330.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

- Moved Stat to the subclasses of InMemoryNode


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -695,6 +696,22 @@
   InMemoryFileSystemTest()
   : FS(/*UseNormalizedPaths=*/false),
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
+
+public:
+  void ExpectHardLink(Twine From, Twine To, const string &ExpectedBuffer) {
+auto OpenedFrom = FS.openFileForRead(From);
+ASSERT_FALSE(OpenedFrom.getError());
+auto OpenedTo = FS.openFileForRead(To);
+ASSERT_FALSE(OpenedTo.getError());
+ASSERT_EQ((*OpenedFrom)->status()->getSize(),
+  (*OpenedTo)->status()->getSize());
+ASSERT_EQ((*OpenedFrom)->status()->getUniqueID(),
+  (*OpenedTo)->status()->getUniqueID());
+ASSERT_EQ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data(),
+  (*OpenedTo)->getBuffer(To)->get()->getBuffer().data());
+ASSERT_EQ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data(),
+  ExpectedBuffer);
+  }
 };
 
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
@@ -958,6 +975,126 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  std::pair From = {"/path/to/FROM/file",
+"content of FROM file"};
+  std::pair To = {"/path/to/TO/file",
+  "content of TO file"};
+  FS.addFile(To.first, 0, MemoryBuffer::getMemBuffer(To.second));
+  EXPECT_TRUE(FS.addHardLink(From.first, To.first));
+  ExpectHardLink(From.first, To.first, To.second.data());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef content = "content of target file";
+  Twine link0 = "/path/to/0/link";
+  Twine link1 = "/path/to/1/link";
+  Twine link2 = "/path/to/2/link";
+  Twine target = "/path/to/target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link2, target));
+  EXPECT_TRUE(FS.addHardLink(link1, link2));
+  EXPECT_TRUE(FS.addHardLink(link0, link1));
+  ExpectHardLink(link0, target, content.data());
+  ExpectHardLink(link1, target, content.data());
+  ExpectHardLink(link2, target, content.data());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  Twine link = "/path/to/link";
+  StringRef content_link = "content of link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content_link));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_TRUE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  StringRef link_content = "different content of link";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(link_content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine link = "/path/to/link";
+  Twine dummy_file = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(dummy_file, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(link, dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  Twine 

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-31 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163549.
usaxena95 marked 15 inline comments as done.
usaxena95 added a comment.

- Made suggested changes.


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -16,7 +16,9 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -697,6 +699,29 @@
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
 };
 
+MATCHER_P3(IsHardLinktTo, FS, Target, ExpectedBuffer, "") {
+  Twine From = arg;
+  Twine To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  if (OpenedFrom.getError())
+return false;
+  auto OpenedTo = FS->openFileForRead(To);
+  if (OpenedTo.getError())
+return false;
+  if ((*OpenedFrom)->status()->getSize() != (*OpenedTo)->status()->getSize())
+return false;
+  if ((*OpenedFrom)->status()->getUniqueID() !=
+  (*OpenedTo)->status()->getUniqueID())
+return false;
+  if ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data() !=
+  ExpectedBuffer)
+return false;
+  if ((*OpenedFrom)->getBuffer(From)->get()->getBuffer().data() !=
+  ExpectedBuffer)
+return false;
+  return true;
+}
+
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
   auto Stat = FS.status("/a");
   ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
@@ -958,6 +983,126 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  Twine FromLink = "/path/to/FROM/link";
+  Twine Target = "/path/to/TO/file";
+  StringRef content = "content of target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinktTo(&FS, Target, content.data()));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef content = "content of target file";
+  Twine link0 = "/path/to/0/link";
+  Twine link1 = "/path/to/1/link";
+  Twine link2 = "/path/to/2/link";
+  Twine target = "/path/to/target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link2, target));
+  EXPECT_TRUE(FS.addHardLink(link1, link2));
+  EXPECT_TRUE(FS.addHardLink(link0, link1));
+  EXPECT_THAT(link0, IsHardLinktTo(&FS, target, content.data()));
+  EXPECT_THAT(link1, IsHardLinktTo(&FS, target, content.data()));
+  EXPECT_THAT(link2, IsHardLinktTo(&FS, target, content.data()));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  Twine link = "/path/to/link";
+  StringRef content_link = "content of link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content_link));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_TRUE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  StringRef link_content = "different content of link";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(link_content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine link = "/path/to/link";
+  Twine dummy_file = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(dummy_file, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(link, dir));
+}
+
+TEST_F(InMemoryF

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-08-31 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

Made the suggested changes.




Comment at: include/clang/Basic/VirtualFileSystem.h:359
+  public:
+  /// Add a HardLink to a File.
+  /// The To path must be an existing file or a hardlink. The From file must 
not

ilya-biryukov wrote:
> Maybe document that it does nothing for directories?
> Also, any reason to not support directories at this point? The limitation 
> seem artificial at this point.
Links to directories cannot be  added with the current logic. Resolving paths 
and iterating directories becomes non trivial. Current implementation supports 
the use case of "file with multiple names" which is mostly sufficient to mimic 
the compilation.



Comment at: lib/Basic/VirtualFileSystem.cpp:529
+public:
+  InMemoryHardLink(Status Stat, InMemoryNode *ResolvedNode)
+  : InMemoryNode(std::move(Stat), IME_HARD_LINK),

ilya-biryukov wrote:
> usaxena95 wrote:
> > ilya-biryukov wrote:
> > > ilya-biryukov wrote:
> > > > Why do we need the Stat?
> > > > We can get it from `ResolveNode` if we want to store a copy. Any reason 
> > > > why it would be different?
> > > ResolveNode can't be `null`, right? Maybe use a reference instead?
> > > Also, maybe make it const?
> > Changed it to reference. Can't make it const as the there it is involved in 
> > methods that are non const (like getResolvedFile returns a pointer, 
> > getBuffer is not const)
> Both methods could be made const, though, right?
> It looks like the buffers are always copied when returned from the file 
> system (because the VFS interface returns a `unique_ptr`).
> `getResolvedFile` can also return a const node.
Since a raw pointer to the resolved file is returned by getResolvedNode (used 
by for lookup) , I have also changed some other raw pointer type to const 
pointer tpye.


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-03 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 marked 16 inline comments as done.
usaxena95 added a comment.

Applied suggested changes.




Comment at: lib/Basic/VirtualFileSystem.cpp:653
+  // Cannot create HardLink from a directory.
+  if (HardLinkTarget && (!isa(HardLinkTarget) || Buffer))
+return false;

ilya-biryukov wrote:
> HardLinkTarget can only be `InMemoryFile`, so maybe change the type of the 
> parameter to `const InMemoryFile*`?
> Clients will be responsible for making sure the target is actually a file, 
> but that seems fine, they already have to resolve the path to the target file.
> 
Moved InMemoryFile from detail: namespace to detail namespace in 
order to be visible in VirtualFileSystem.h



Comment at: unittests/Basic/VirtualFileSystemTest.cpp:705
+  Twine To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  if (OpenedFrom.getError())

ilya-biryukov wrote:
> This matcher is pretty complicated and tests multiple things.
> If it fails, it might be hard to track down what exactly went wrong.
> 
> Given the name, it seems reasonable for it to simply test that both paths 
> point to the same unique-id.
> We don't have to test every other invariant (sizes are the same, buffers are 
> the same) on all the links we create, one test assertion per invariant should 
> be enough (sizes are the same, buffers are the same, etc)

Removed the check for Buffer and size from the matcher.  Added the test for 
size and buffer in the smaller AddHardLinkTest


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-03 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163713.
usaxena95 marked 2 inline comments as done.
usaxena95 added a comment.

- applied suggested changes


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -16,7 +16,9 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -697,6 +699,16 @@
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
 };
 
+MATCHER_P2(IsHardLinkTo, FS, Target, "") {
+  Twine From = arg;
+  Twine To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  auto OpenedTo = FS->openFileForRead(To);
+  return !(OpenedFrom.getError() || OpenedTo.getError() ||
+   (*OpenedFrom)->status()->getUniqueID() !=
+   (*OpenedTo)->status()->getUniqueID());
+}
+
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
   auto Stat = FS.status("/a");
   ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
@@ -958,6 +970,129 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  Twine FromLink = "/path/to/FROM/link";
+  Twine Target = "/path/to/TO/file";
+  StringRef content = "content of target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
+  EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize());
+  EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() ==
+  FS.getBufferForFile(Target)->get()->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef content = "content of target file";
+  Twine link0 = "/path/to/0/link";
+  Twine link1 = "/path/to/1/link";
+  Twine link2 = "/path/to/2/link";
+  Twine target = "/path/to/target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link2, target));
+  EXPECT_TRUE(FS.addHardLink(link1, link2));
+  EXPECT_TRUE(FS.addHardLink(link0, link1));
+  EXPECT_THAT(link0, IsHardLinkTo(&FS, target));
+  EXPECT_THAT(link1, IsHardLinkTo(&FS, target));
+  EXPECT_THAT(link2, IsHardLinkTo(&FS, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  Twine link = "/path/to/link";
+  StringRef content_link = "content of link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content_link));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_TRUE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  StringRef link_content = "different content of link";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(link_content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine link = "/path/to/link";
+  Twine dummy_file = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(dummy_file, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(link, dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine target = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-03 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163720.
usaxena95 added a comment.

- Moved helper function into anonymous namespace


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -16,7 +16,9 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -697,6 +699,16 @@
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
 };
 
+MATCHER_P2(IsHardLinkTo, FS, Target, "") {
+  Twine From = arg;
+  Twine To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  auto OpenedTo = FS->openFileForRead(To);
+  return !(OpenedFrom.getError() || OpenedTo.getError() ||
+   (*OpenedFrom)->status()->getUniqueID() !=
+   (*OpenedTo)->status()->getUniqueID());
+}
+
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
   auto Stat = FS.status("/a");
   ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
@@ -958,6 +970,129 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  Twine FromLink = "/path/to/FROM/link";
+  Twine Target = "/path/to/TO/file";
+  StringRef content = "content of target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
+  EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize());
+  EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() ==
+  FS.getBufferForFile(Target)->get()->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef content = "content of target file";
+  Twine link0 = "/path/to/0/link";
+  Twine link1 = "/path/to/1/link";
+  Twine link2 = "/path/to/2/link";
+  Twine target = "/path/to/target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link2, target));
+  EXPECT_TRUE(FS.addHardLink(link1, link2));
+  EXPECT_TRUE(FS.addHardLink(link0, link1));
+  EXPECT_THAT(link0, IsHardLinkTo(&FS, target));
+  EXPECT_THAT(link1, IsHardLinkTo(&FS, target));
+  EXPECT_THAT(link2, IsHardLinkTo(&FS, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  Twine link = "/path/to/link";
+  StringRef content_link = "content of link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content_link));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addHardLink(link, target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_TRUE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  Twine link = "/path/to/link";
+  Twine target = "/path/to/target";
+  StringRef content = "content of target";
+  StringRef link_content = "different content of link";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_TRUE(FS.addHardLink(link, target));
+  EXPECT_FALSE(FS.addFile(link, 0, MemoryBuffer::getMemBuffer(link_content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine link = "/path/to/link";
+  Twine dummy_file = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(dummy_file, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(link, dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  Twine dir = "path/to/dummy/dir";
+  Twine target = dir + "/target";
+  StringRef content = "content of target";
+  EXPECT_TRUE(FS.addFile(target, 0, MemoryBuffer::getMemBuffer(content)));
+  EXPECT_FALSE(FS.addHardLink(di

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-03 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

Applied the changes suggested.




Comment at: lib/Basic/VirtualFileSystem.cpp:677
+if (HardLinkTarget)
+  Child.reset(new detail::InMemoryHardLink(P.str(), *HardLinkTarget));
+else {

ilya-biryukov wrote:
> NIT: `.str()` seems redundant
Here P is a Twine here which cannot be converted to StringRef


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-03 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163739.
usaxena95 marked 14 inline comments as done.
usaxena95 added a comment.

- applied changes


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -16,7 +16,9 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -697,6 +699,16 @@
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
 };
 
+MATCHER_P2(IsHardLinkTo, FS, Target, "") {
+  StringRef From = arg;
+  StringRef To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  auto OpenedTo = FS->openFileForRead(To);
+  return !(OpenedFrom.getError() || OpenedTo.getError() ||
+   (*OpenedFrom)->status()->getUniqueID() !=
+   (*OpenedTo)->status()->getUniqueID());
+}
+
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
   auto Stat = FS.status("/a");
   ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
@@ -958,6 +970,108 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  StringRef FromLink = "/path/to/FROM/link";
+  StringRef Target = "/path/to/TO/file";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
+  EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize());
+  EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() ==
+  FS.getBufferForFile(Target)->get()->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef Link0 = "/path/to/0/link";
+  StringRef Link1 = "/path/to/1/link";
+  StringRef Link2 = "/path/to/2/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file"));
+  EXPECT_TRUE(FS.addHardLink(Link2, Target));
+  EXPECT_TRUE(FS.addHardLink(Link1, Link2));
+  EXPECT_TRUE(FS.addHardLink(Link0, Link1));
+  EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link"));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  StringRef LinkContent = "different content of link";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Link = "/path/to/link";
+  StringRef File = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Link, Dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Target = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Dir, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) {
+  StringRef CommonContent = "content

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-04 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 163785.
usaxena95 marked 9 inline comments as done.
usaxena95 added a comment.

- fixed the style issues


Repository:
  rC Clang

https://reviews.llvm.org/D51359

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -16,7 +16,9 @@
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include 
+#include 
 
 using namespace clang;
 using namespace llvm;
@@ -697,6 +699,16 @@
 NormalizedFS(/*UseNormalizedPaths=*/true) {}
 };
 
+MATCHER_P2(IsHardLinkTo, FS, Target, "") {
+  StringRef From = arg;
+  StringRef To = Target;
+  auto OpenedFrom = FS->openFileForRead(From);
+  auto OpenedTo = FS->openFileForRead(To);
+  return !OpenedFrom.getError() && !OpenedTo.getError() &&
+ (*OpenedFrom)->status()->getUniqueID() ==
+ (*OpenedTo)->status()->getUniqueID();
+}
+
 TEST_F(InMemoryFileSystemTest, IsEmpty) {
   auto Stat = FS.status("/a");
   ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
@@ -958,6 +970,108 @@
   ASSERT_EQ("../b/c", getPosixPath(It->getName()));
 }
 
+TEST_F(InMemoryFileSystemTest, AddHardLinkToFile) {
+  StringRef FromLink = "/path/to/FROM/link";
+  StringRef Target = "/path/to/TO/file";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(FromLink, Target));
+  EXPECT_THAT(FromLink, IsHardLinkTo(&FS, Target));
+  EXPECT_TRUE(FS.status(FromLink)->getSize() == FS.status(Target)->getSize());
+  EXPECT_TRUE(FS.getBufferForFile(FromLink)->get()->getBuffer() ==
+  FS.getBufferForFile(Target)->get()->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkInChainPattern) {
+  StringRef Link0 = "/path/to/0/link";
+  StringRef Link1 = "/path/to/1/link";
+  StringRef Link2 = "/path/to/2/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target file"));
+  EXPECT_TRUE(FS.addHardLink(Link2, Target));
+  EXPECT_TRUE(FS.addHardLink(Link1, Link2));
+  EXPECT_TRUE(FS.addHardLink(Link0, Link1));
+  EXPECT_THAT(Link0, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link1, IsHardLinkTo(&FS, Target));
+  EXPECT_THAT(Link2, IsHardLinkTo(&FS, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToAFileThatWasNotAddedBefore) {
+  EXPECT_FALSE(FS.addHardLink("/path/to/link", "/path/to/target"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromAFileThatWasAddedBefore) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  FS.addFile(Link, 0, MemoryBuffer::getMemBuffer("content of link"));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddSameHardLinkMoreThanOnce) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  FS.addFile(Target, 0, MemoryBuffer::getMemBuffer("content of target"));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addHardLink(Link, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithSameContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_TRUE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(Content)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileInPlaceOfAHardLinkWithDifferentContent) {
+  StringRef Link = "/path/to/link";
+  StringRef Target = "/path/to/target";
+  StringRef Content = "content of target";
+  StringRef LinkContent = "different content of link";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_TRUE(FS.addHardLink(Link, Target));
+  EXPECT_FALSE(FS.addFile(Link, 0, MemoryBuffer::getMemBuffer(LinkContent)));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkToADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Link = "/path/to/link";
+  StringRef File = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(File, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Link, Dir));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkFromADirectory) {
+  StringRef Dir = "path/to/dummy/dir";
+  StringRef Target = "path/to/dummy/dir/target";
+  StringRef Content = "content of target";
+  EXPECT_TRUE(FS.addFile(Target, 0, MemoryBuffer::getMemBuffer(Content)));
+  EXPECT_FALSE(FS.addHardLink(Dir, Target));
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinkUnderAFile) {
+  StringRef CommonContent = "conten

[PATCH] D51359: Adding HardLink Support to VirtualFileSystem.

2018-09-04 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

I don't have commit access. Can you  please submit this ?


Repository:
  rC Clang

https://reviews.llvm.org/D51359



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


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-27 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: cfe-commits, mgrang.

Some files are only Statted by Clang and not read. Clang mostly uses
them for checking the existence of some files and in rare cases uses the
value of the Status to proceed further (for example while loading
module files, it checks the sizes of some files).

This change adds support to represent files that are supposed to be only
statted by Clang.


Repository:
  rC Clang

https://reviews.llvm.org/D52620

Files:
  include/clang/Basic/VirtualFileSystem.h
  lib/Basic/VirtualFileSystem.cpp
  unittests/Basic/VirtualFileSystemTest.cpp

Index: unittests/Basic/VirtualFileSystemTest.cpp
===
--- unittests/Basic/VirtualFileSystemTest.cpp
+++ unittests/Basic/VirtualFileSystemTest.cpp
@@ -553,8 +553,8 @@
   for (DirIter E; !EC && I != E; I.increment(EC))
 InputToCheck.push_back(I->path());
 
-  llvm::sort(InputToCheck);
-  llvm::sort(Expected);
+  llvm::sort(InputToCheck.begin(), InputToCheck.end());
+  llvm::sort(Expected.begin(), Expected.end());
   EXPECT_EQ(InputToCheck.size(), Expected.size());
 
   unsigned LastElt = std::min(InputToCheck.size(), Expected.size());
@@ -1063,15 +1063,50 @@
 TEST_F(InMemoryFileSystemTest, RecursiveIterationWithHardLink) {
   std::error_code EC;
   FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content string"));
+  FS.addStatOnlyFile("/a/d", 0, 10);
   EXPECT_TRUE(FS.addHardLink("/c/d", "/a/b"));
   auto I = vfs::recursive_directory_iterator(FS, "/", EC);
   ASSERT_FALSE(EC);
   std::vector Nodes;
   for (auto E = vfs::recursive_directory_iterator(); !EC && I != E;
I.increment(EC)) {
 Nodes.push_back(getPosixPath(I->path()));
   }
-  EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/b", "/c", "/c/d"));
+  EXPECT_THAT(Nodes, testing::UnorderedElementsAre("/a", "/a/d", "/a/b",
+   "/c", "/c/d"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddStatOnlyFileWithCorrectSize) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  auto Stat = FS.status("/a/b");
+  EXPECT_EQ(Stat.get().getSize(), 10);
+}
+
+TEST_F(InMemoryFileSystemTest, AddMultipleFilesUnderStatOnlyFile) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  EXPECT_FALSE(FS.addStatOnlyFile("/a/b", 0, 11));
+  EXPECT_TRUE(FS.addStatOnlyFile("/a/b", 0, 10));
+  EXPECT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("content")));
+}
+
+TEST_F(InMemoryFileSystemTest, DeathWhenBufferRequestedForStatOnlyFile) {
+  FS.addStatOnlyFile("/a/b", 0, 10);
+  EXPECT_DEATH(FS.getBufferForFile("/a/b"),
+   "Cannot get buffer for StatOnlyFile");
+}
+
+TEST_F(InMemoryFileSystemTest, AddHardLinksToStatOnlyFile) {
+  FS.addStatOnlyFile("/target", 0, 10);
+  FS.addHardLink("/link1", "/target");
+  FS.addHardLink("/link2", "/link1");
+  EXPECT_THAT("/link1", IsHardLinkTo(&FS, "/target"));
+  EXPECT_THAT("/link2", IsHardLinkTo(&FS, "/target"));
+}
+
+TEST_F(InMemoryFileSystemTest, AddFileUnderHardLinkToStatOnlyFile) {
+  FS.addStatOnlyFile("/target", 0, 10);
+  FS.addHardLink("/link", "/target");
+  EXPECT_FALSE(FS.addFile("/link",  0, MemoryBuffer::getMemBuffer("content")));
 }
 
 // NOTE: in the tests below, we use '//root/' as our root directory, since it is
Index: lib/Basic/VirtualFileSystem.cpp
===
--- lib/Basic/VirtualFileSystem.cpp
+++ lib/Basic/VirtualFileSystem.cpp
@@ -492,20 +492,26 @@
 class InMemoryFile : public InMemoryNode {
   Status Stat;
   std::unique_ptr Buffer;
+  bool StatOnlyFile;
 
 public:
-  InMemoryFile(Status Stat, std::unique_ptr Buffer)
+  InMemoryFile(Status Stat, std::unique_ptr Buffer,
+   bool StatOnlyFile)
   : InMemoryNode(Stat.getName(), IME_File), Stat(std::move(Stat)),
-Buffer(std::move(Buffer)) {}
+Buffer(std::move(Buffer)), StatOnlyFile(StatOnlyFile) {}
 
   /// Return the \p Status for this node. \p RequestedName should be the name
   /// through which the caller referred to this node. It will override
   /// \p Status::Name in the return value, to mimic the behavior of \p RealFile.
   Status getStatus(StringRef RequestedName) const {
 return Status::copyWithNewName(Stat, RequestedName);
   }
-  llvm::MemoryBuffer *getBuffer() const { return Buffer.get(); }
+  llvm::MemoryBuffer *getBuffer() const {
+assert(!StatOnlyFile && "Cannot get buffer for StatOnlyFile");
+return Buffer.get();
+  }
 
+  bool IsStatOnlyFile() const { return StatOnlyFile; }
   std::string toString(unsigned Indent) const override {
 return (std::string(Indent, ' ') + Stat.getName() + "\n").str();
   }
@@ -640,7 +646,8 @@
  Optional Group,
  Optional Type,
  Optional Perms,
- const detail::InMemoryFile *HardLinkTarget) {
+ const detail::InMemoryFile *HardLinkTarge

[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

> it sounds like this is for record-replay.

Yes this is for record-replay purpose.

> What are these files in practice?

During loading a modules the files that were required to make the module are 
stat()ed and their sizes are used to verify that the module is still valid. 
There are occurrences of more stat() only files (apart from the use in modules) 
which I am not aware of.

> In the replayed compilation, we assume the accessed files are the same, is it 
> safe to assume we never read files we previously stat()ed?

I would call it a requirement instead of an assumption. The replay must be 
exactly the same (even the file stats and reads). If Clang reads the file in 
replay which was only stat()ed during compilation, it indicates non-determinism 
or something wrong (in clang or FS).
We currently deal with such files by adding empty buffers for them based on 
this assumption/requirement only.

> it seems like this could also be achieved with an overlayFS adding a simple 
> specialized FS that only provides the stat-only files. If this is a 
> relatively niche feature, cramming it into InMemoryFileSystem may not be the 
> best option. Any thoughts on the tradeoff here?

We can reuse the InMemoryFS to make another FS which just serves stat-only 
files. A tradeoff I can think of is: we might need to store a random buffer of 
required size to make final status of the file correct.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



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


[PATCH] D52620: Added Support for StatOnly Files in VFS.

2018-09-28 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: lib/Basic/VirtualFileSystem.cpp:2097
 void YAMLVFSWriter::write(llvm::raw_ostream &OS) {
-  llvm::sort(Mappings, [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {
+  llvm::sort(Mappings.begin(), Mappings.end(),
+ [](const YAMLVFSEntry &LHS, const YAMLVFSEntry &RHS) {

kbobyrev wrote:
> This used `llvm::sort(Container &&C, Compare Comp)` before, I would think 
> that the range-based API is the preferred one. There's also a cleanup patch 
> migrating STL-like calls to idiomatic LLVM's STL Extension API: D52576.
I think these are some very recent changes and does not belong to my patch. 
Will sync these. Thanks for pointing out.


Repository:
  rC Clang

https://reviews.llvm.org/D52620



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


[PATCH] D58278: Prepare ground for re-lexing modular headers.

2019-02-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

+cc myself


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D58278



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


[PATCH] D65866: Code completion should not ignore default parameters in functions.

2019-08-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: sammccall.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous.
Herald added a project: clang.

Inorder to display the default arguments we must process the
CK_Optional chunks of CodeCompletionString while creating the Signature.

We do not create placeholders for default arguments.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65866

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


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,6 +10,7 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
+#include "Logger.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -939,6 +940,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -32,6 +32,21 @@
   }
 }
 
+void appendCodeCompletionString(const CodeCompletionString &CCS, std::string 
*Out) {
+  for (const CodeCompletionString::Chunk &C : CCS) {
+switch (C.Kind) {
+case CodeCompletionString::CK_Optional:
+  assert(C.Optional &&
+ "Expected the optional code completion string to be non-null.");
+  appendCodeCompletionString(*C.Optional, Out);
+  break;
+default:
+  *Out += C.Text;
+  break;
+}
+  }
+}
+
 bool looksLikeDocComment(llvm::StringRef CommentText) {
   // We don't report comments that only contain "special" chars.
   // This avoids reporting various delimiters, like:
@@ -138,6 +153,10 @@
   *Snippet += Chunk.Text;
   break;
 case CodeCompletionString::CK_Optional:
+  assert(Chunk.Optional &&
+ "Expected the optional code completion string to be non-null.");  

+  // No need to create placeholders for default arguments in Snippet.
+  appendCodeCompletionString(*Chunk.Optional, Signature);
   break;
 case CodeCompletionString::CK_Placeholder:
   *Signature += Chunk.Text;


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,6 +10,7 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
+#include "Logger.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -939,6 +940,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
=

[PATCH] D65866: Code completion should not ignore default parameters in functions.

2019-08-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 213871.
usaxena95 added a comment.

Removed unused include of logger.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65866

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


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -939,6 +939,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -32,6 +32,21 @@
   }
 }
 
+void appendCodeCompletionString(const CodeCompletionString &CCS, std::string 
*Out) {
+  for (const CodeCompletionString::Chunk &C : CCS) {
+switch (C.Kind) {
+case CodeCompletionString::CK_Optional:
+  assert(C.Optional &&
+ "Expected the optional code completion string to be non-null.");
+  appendCodeCompletionString(*C.Optional, Out);
+  break;
+default:
+  *Out += C.Text;
+  break;
+}
+  }
+}
+
 bool looksLikeDocComment(llvm::StringRef CommentText) {
   // We don't report comments that only contain "special" chars.
   // This avoids reporting various delimiters, like:
@@ -138,6 +153,10 @@
   *Snippet += Chunk.Text;
   break;
 case CodeCompletionString::CK_Optional:
+  assert(Chunk.Optional &&
+ "Expected the optional code completion string to be non-null.");  

+  // No need to create placeholders for default arguments in Snippet.
+  appendCodeCompletionString(*Chunk.Optional, Signature);
   break;
 case CodeCompletionString::CK_Placeholder:
   *Signature += Chunk.Text;


Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -939,6 +939,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -32,6 +32,21 @@
   }
 }
 
+void appendCodeCompletionString(const CodeCompletionString &CCS, std::string *Out) {
+  for (const CodeCompletionString::Chunk &C : CCS) {
+switch (C.Kind) {
+case CodeCompletionString::CK_Optional:
+  assert(C.Optional &&
+ "Expected the optional code completion string to be non-null.");
+  appendCodeCompletionString(*C.Optional, Out);
+  break;

[PATCH] D65866: Code completion should not ignore default parameters in functions.

2019-08-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 213926.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

Added tests in CodeCompletionStringsTests.cpp
Resolved comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65866

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

Index: clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
@@ -90,6 +90,30 @@
   EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
 }
 
+TEST_F(CompletionStringTest, FunctionWithDefaultParams) {
+  // return_type foo(p1, p2 = 0, p3 = 0)
+  Builder.AddChunk(CodeCompletionString::CK_Comma);
+  Builder.AddTypedTextChunk("p3 = 0");
+  auto *DefaultParam2 = Builder.TakeString();
+
+  Builder.AddChunk(CodeCompletionString::CK_Comma);
+  Builder.AddTypedTextChunk("p2 = 0");
+  Builder.AddOptionalChunk(DefaultParam2);
+  auto* DefaultParam1 = Builder.TakeString();
+
+  Builder.AddResultTypeChunk("return_type");
+  Builder.AddTypedTextChunk("Foo");
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("p1");
+  Builder.AddOptionalChunk(DefaultParam1);
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+
+  auto *CCS = Builder.TakeString();
+  computeSignature(*CCS);
+  EXPECT_EQ(Signature, "(p1, p2 = 0, p3 = 0)");
+  EXPECT_EQ(Snippet, "(${1:p1})");
+}
+
 TEST_F(CompletionStringTest, EscapeSnippet) {
   Builder.AddTypedTextChunk("Foo");
   Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -939,6 +939,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -32,6 +32,21 @@
   }
 }
 
+void appendOptionalChunk(const CodeCompletionString &CCS, std::string *Out) {
+  for (const CodeCompletionString::Chunk &C : CCS) {
+switch (C.Kind) {
+case CodeCompletionString::CK_Optional:
+  assert(C.Optional &&
+ "Expected the optional code completion string to be non-null.");
+  appendOptionalChunk(*C.Optional, Out);
+  break;
+default:
+  *Out += C.Text;
+  break;
+}
+  }
+}
+
 bool looksLikeDocComment(llvm::StringRef CommentText) {
   // We don't report comments that only contain "special" chars.
   // This avoids reporting various delimiters, like:
@@ -138,6 +153,9 @@
   *Snippet += Chunk.Text;
   break;
 case CodeCompletionString::CK_Optional:
+  assert(Chunk.Optional);  
+  // No need to create placeholders for default arguments in Snippet.
+  appendOptionalChunk(*Chunk.Optional, Signature);
   break;
 case CodeCompletionString::CK_Placeholder:
   *Signature += Chunk.Text;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65866: Code completion should not ignore default parameters in functions.

2019-08-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 213927.
usaxena95 added a comment.

Formatted new test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65866

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

Index: clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompletionStringsTests.cpp
@@ -90,6 +90,30 @@
   EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
 }
 
+TEST_F(CompletionStringTest, FunctionWithDefaultParams) {
+  // return_type foo(p1, p2 = 0, p3 = 0)
+  Builder.AddChunk(CodeCompletionString::CK_Comma);
+  Builder.AddTypedTextChunk("p3 = 0");
+  auto *DefaultParam2 = Builder.TakeString();
+
+  Builder.AddChunk(CodeCompletionString::CK_Comma);
+  Builder.AddTypedTextChunk("p2 = 0");
+  Builder.AddOptionalChunk(DefaultParam2);
+  auto *DefaultParam1 = Builder.TakeString();
+
+  Builder.AddResultTypeChunk("return_type");
+  Builder.AddTypedTextChunk("Foo");
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+  Builder.AddPlaceholderChunk("p1");
+  Builder.AddOptionalChunk(DefaultParam1);
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+
+  auto *CCS = Builder.TakeString();
+  computeSignature(*CCS);
+  EXPECT_EQ(Signature, "(p1, p2 = 0, p3 = 0)");
+  EXPECT_EQ(Snippet, "(${1:p1})");
+}
+
 TEST_F(CompletionStringTest, EscapeSnippet) {
   Builder.AddTypedTextChunk("Foo");
   Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -939,6 +939,25 @@
 
   EXPECT_TRUE(Results.Completions.empty());
 }
+
+TEST(CompletionTest, DefaultArgs) {
+  clangd::CodeCompleteOptions Opts;
+  std::string Context = R"cpp(
+int X(int A = 0);
+int Y(int A, int B = 0);
+int Z(int A, int B = 0, int C = 0, int D = 0);
+  )cpp";
+  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,
+  UnorderedElementsAre(Labeled("X(int A = 0)")));
+  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,
+  UnorderedElementsAre(AllOf(Labeled("Y(int A, int B = 0)"),
+ SnippetSuffix("(${1:int A})";
+  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,
+  UnorderedElementsAre(
+  AllOf(Labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),
+SnippetSuffix("(${1:int A})";
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
  std::vector IndexSymbols = {}) {
   std::unique_ptr Index;
Index: clang-tools-extra/clangd/CodeCompletionStrings.cpp
===
--- clang-tools-extra/clangd/CodeCompletionStrings.cpp
+++ clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -32,6 +32,21 @@
   }
 }
 
+void appendOptionalChunk(const CodeCompletionString &CCS, std::string *Out) {
+  for (const CodeCompletionString::Chunk &C : CCS) {
+switch (C.Kind) {
+case CodeCompletionString::CK_Optional:
+  assert(C.Optional &&
+ "Expected the optional code completion string to be non-null.");
+  appendOptionalChunk(*C.Optional, Out);
+  break;
+default:
+  *Out += C.Text;
+  break;
+}
+  }
+}
+
 bool looksLikeDocComment(llvm::StringRef CommentText) {
   // We don't report comments that only contain "special" chars.
   // This avoids reporting various delimiters, like:
@@ -138,6 +153,9 @@
   *Snippet += Chunk.Text;
   break;
 case CodeCompletionString::CK_Optional:
+  assert(Chunk.Optional);  
+  // No need to create placeholders for default arguments in Snippet.
+  appendOptionalChunk(*Chunk.Optional, Signature);
   break;
 case CodeCompletionString::CK_Placeholder:
   *Signature += Chunk.Text;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-13 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220071.
usaxena95 marked 13 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67358

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -0,0 +1,143 @@
+//===-- SemanticSelectionTests.cpp  *- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Annotations.h"
+#include "Matchers.h"
+#include "Protocol.h"
+#include "SemanticSelection.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::ElementsAreArray;
+
+TEST(SemanticSelection, All) {
+  const char *Tests[] = {
+  R"cpp( // Single statement in a function body.
+[[void func() [[{
+  int v = [[1^00;]]
+}
+  )cpp",
+  R"cpp( // Expression
+[[void func() [[{
+  int a = 1;
+  // int v = (10 + 2) * (a + a);
+  int v = (10^]] + 2]])]] * (a + a);]]
+}
+  )cpp",
+  R"cpp( // Function call.
+int add(int x, int y) { return x + y; }
+[[void callee() [[{
+  // int res = add(11, 22);
+  int res = [[add([[1^1]], 22);]]
+}
+  )cpp",
+  R"cpp( // Tricky macros.
+#define MUL ) * (
+[[void func() [[{
+  // int var = (4 + 15 MUL 6 + 10);
+  int var = ([[4 + [[1^5 MUL]] 6 + 10);]]
+}
+   )cpp",
+  R"cpp( // Cursor inside a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HASH(2^3]] + 34]]);]]
+}
+   )cpp",
+  R"cpp( // Cursor on a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HA^SH(23);]]
+}
+   )cpp",
+  R"cpp( // Multiple declaration.
+[[void func() [[{
+  int var1, var^2]], var3;]]
+}
+   )cpp",
+  R"cpp( // Before comment.
+[[void func() [[{
+  int var1 = 1;
+  int var2 = var1]]^ /*some comment*/ + 41;]]
+}
+   )cpp",
+  // Empty file.
+  "^",
+  // FIXME: We should get the whole DeclStmt as a range.
+  R"cpp( // Single statement in TU.
+[[int v = [[1^00;
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor at end of VarDecl.
+void func() {
+  int v = 100 + 100^;
+}
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor in between spaces.
+void func() {
+  int v = 100 + ^  100;
+}
+  )cpp",
+  // Structs.
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = AAA::BBB::c^cc]]();]]
+}
+  )cpp",
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = [[AA^A]]::]]BBB::]]ccc]]();]]
+}
+  )cpp",
+  R"cpp( // Inside struct.
+struct A { static int a(); };
+[[struct B { 
+  [[static int b() [[{
+[[return 1^1]] + 2;
+  }
+}]];
+  )cpp",
+  // Namespaces.
+  R"cpp( 
+[[namespace nsa { 
+  [[namespace nsb { 
+static int ccc();
+[[void func() [[{
+  // int x = nsa::nsb::ccc();
+  int x = nsa::nsb::cc^c]]();]]
+}
+  }]]
+}]]
+  )cpp",
+
+  };
+
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+auto AST = TestTU::withCode(T.code()).build();
+EXPECT_THAT(llvm::cantFail(getSemanticRanges(AST, T.point())),
+ElementsAreArray(T.ranges()))
+<< Test;
+  }
+}
+} // namespace
+} // namespace clangd
+} // namespace 

[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-13 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/SemanticSelection.cpp:33
+  if (!Offset) {
+llvm::errs() << "Unable to convert postion to offset";
+return {};

sammccall wrote:
> we use log() or elog() for this, make sure you include Offset.takeError() for 
> the original message
> 
> Alternatively, you might consider returning Expected 
> so the error gets propagated to the client (as this really is a client error)
Returning Expected> now to propagate the error.



Comment at: clang-tools-extra/clangd/SemanticSelection.cpp:39
+  SelectionTree ST(AST.getASTContext(), AST.getTokens(), *Offset);
+  for (const auto *Node = ST.commonAncestor(); Node != nullptr;
+   Node = Node->Parent) {

sammccall wrote:
> I think you probably want to bail out once you hit TranslationUnitDecl.
> 
> And maybe at namespace decls? Though I have often in my editor wondered 
> "what's the enclosing namespace"...
Bailing out once we hit the TUDecl. I am not sure about exiting on namespace 
decl. I am keeping this for now. We can remove this later if the need be.



Comment at: clang-tools-extra/clangd/SemanticSelection.cpp:45
+}
+SourceLocation BeginLoc = SR.getBegin();
+SourceLocation EndLoc =

sammccall wrote:
> Ah, this will work if the start and the end of the AST node are written 
> directly in the file, and no macros are involved. But try 
> `toHalfOpenFileRange` in `SourceCode.h`, which should work in a lot more 
> cases.
> 
> In particular, this should work:
> ```
> #define INC(X) X + 1
> int a, b;
> int c = INC(a * b);
> ^
> ~
> ~
> ~~
> ~~
> ```
Interesting. This works fine in such cases. Thanks.
Though it works strangely with these ugly macros. I guess this is because it 
tries to follow the macro expansion.
```
#define MUL ) * (
int var = (4 + 15 MUL 6 + 10);
^
   ~~
   ~~
  ~~~
```



Comment at: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp:115
+[[void func() [[{
+  // int x = nsa::nsb::ccc();
+  int x = nsa::nsb::cc^c]]();]]

sammccall wrote:
> why commented out?
Since the statement contains many [[ and ]], I have added the actual statement 
in comments to make it more readable. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67358



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


[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-13 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220074.
usaxena95 added a comment.

Minor changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67358

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -0,0 +1,143 @@
+//===-- SemanticSelectionTests.cpp  *- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Annotations.h"
+#include "Matchers.h"
+#include "Protocol.h"
+#include "SemanticSelection.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::ElementsAreArray;
+
+TEST(SemanticSelection, All) {
+  const char *Tests[] = {
+  R"cpp( // Single statement in a function body.
+[[void func() [[{
+  int v = [[1^00;]]
+}
+  )cpp",
+  R"cpp( // Expression
+[[void func() [[{
+  int a = 1;
+  // int v = (10 + 2) * (a + a);
+  int v = (10^]] + 2]])]] * (a + a);]]
+}
+  )cpp",
+  R"cpp( // Function call.
+int add(int x, int y) { return x + y; }
+[[void callee() [[{
+  // int res = add(11, 22);
+  int res = [[add([[1^1]], 22);]]
+}
+  )cpp",
+  R"cpp( // Tricky macros.
+#define MUL ) * (
+[[void func() [[{
+  // int var = (4 + 15 MUL 6 + 10);
+  int var = ([[4 + [[1^5 MUL]] 6 + 10);]]
+}
+   )cpp",
+  R"cpp( // Cursor inside a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HASH(2^3]] + 34]]);]]
+}
+   )cpp",
+  R"cpp( // Cursor on a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HA^SH(23);]]
+}
+   )cpp",
+  R"cpp( // Multiple declaration.
+[[void func() [[{
+  int var1, var^2]], var3;]]
+}
+   )cpp",
+  R"cpp( // Before comment.
+[[void func() [[{
+  int var1 = 1;
+  int var2 = var1]]^ /*some comment*/ + 41;]]
+}
+   )cpp",
+  // Empty file.
+  "^",
+  // FIXME: We should get the whole DeclStmt as a range.
+  R"cpp( // Single statement in TU.
+[[int v = [[1^00;
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor at end of VarDecl.
+void func() {
+  int v = 100 + 100^;
+}
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor in between spaces.
+void func() {
+  int v = 100 + ^  100;
+}
+  )cpp",
+  // Structs.
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = AAA::BBB::c^cc]]();]]
+}
+  )cpp",
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = [[AA^A]]::]]BBB::]]ccc]]();]]
+}
+  )cpp",
+  R"cpp( // Inside struct.
+struct A { static int a(); };
+[[struct B { 
+  [[static int b() [[{
+[[return 1^1]] + 2;
+  }
+}]];
+  )cpp",
+  // Namespaces.
+  R"cpp( 
+[[namespace nsa { 
+  [[namespace nsb { 
+static int ccc();
+[[void func() [[{
+  // int x = nsa::nsb::ccc();
+  int x = nsa::nsb::cc^c]]();]]
+}
+  }]]
+}]]
+  )cpp",
+
+  };
+
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+auto AST = TestTU::withCode(T.code()).build();
+EXPECT_THAT(llvm::cantFail(getSemanticRanges(AST, T.point())),
+ElementsAreArray(T.ranges()))
+<< Test;
+  }
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
\ No newline at end of file
Index: clang-too

[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-13 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220075.
usaxena95 added a comment.

Remove extraneous namespace comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67358

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -0,0 +1,143 @@
+//===-- SemanticSelectionTests.cpp  *- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Annotations.h"
+#include "Matchers.h"
+#include "Protocol.h"
+#include "SemanticSelection.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::ElementsAreArray;
+
+TEST(SemanticSelection, All) {
+  const char *Tests[] = {
+  R"cpp( // Single statement in a function body.
+[[void func() [[{
+  int v = [[1^00;]]
+}
+  )cpp",
+  R"cpp( // Expression
+[[void func() [[{
+  int a = 1;
+  // int v = (10 + 2) * (a + a);
+  int v = (10^]] + 2]])]] * (a + a);]]
+}
+  )cpp",
+  R"cpp( // Function call.
+int add(int x, int y) { return x + y; }
+[[void callee() [[{
+  // int res = add(11, 22);
+  int res = [[add([[1^1]], 22);]]
+}
+  )cpp",
+  R"cpp( // Tricky macros.
+#define MUL ) * (
+[[void func() [[{
+  // int var = (4 + 15 MUL 6 + 10);
+  int var = ([[4 + [[1^5 MUL]] 6 + 10);]]
+}
+   )cpp",
+  R"cpp( // Cursor inside a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HASH(2^3]] + 34]]);]]
+}
+   )cpp",
+  R"cpp( // Cursor on a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HA^SH(23);]]
+}
+   )cpp",
+  R"cpp( // Multiple declaration.
+[[void func() [[{
+  int var1, var^2]], var3;]]
+}
+   )cpp",
+  R"cpp( // Before comment.
+[[void func() [[{
+  int var1 = 1;
+  int var2 = var1]]^ /*some comment*/ + 41;]]
+}
+   )cpp",
+  // Empty file.
+  "^",
+  // FIXME: We should get the whole DeclStmt as a range.
+  R"cpp( // Single statement in TU.
+[[int v = [[1^00;
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor at end of VarDecl.
+void func() {
+  int v = 100 + 100^;
+}
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor in between spaces.
+void func() {
+  int v = 100 + ^  100;
+}
+  )cpp",
+  // Structs.
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = AAA::BBB::c^cc]]();]]
+}
+  )cpp",
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = [[AA^A]]::]]BBB::]]ccc]]();]]
+}
+  )cpp",
+  R"cpp( // Inside struct.
+struct A { static int a(); };
+[[struct B { 
+  [[static int b() [[{
+[[return 1^1]] + 2;
+  }
+}]];
+  )cpp",
+  // Namespaces.
+  R"cpp( 
+[[namespace nsa { 
+  [[namespace nsb { 
+static int ccc();
+[[void func() [[{
+  // int x = nsa::nsb::ccc();
+  int x = nsa::nsb::cc^c]]();]]
+}
+  }]]
+}]]
+  )cpp",
+
+  };
+
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+auto AST = TestTU::withCode(T.code()).build();
+EXPECT_THAT(llvm::cantFail(getSemanticRanges(AST, T.point())),
+ElementsAreArray(T.ranges()))
+<< Test;
+  }
+}
+} // namespace
+} // namespace clangd
+} // namespace clang
\ No newline at end of

[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-16 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220303.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

Resolved comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67358

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -0,0 +1,143 @@
+//===-- SemanticSelectionTests.cpp  *- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "Annotations.h"
+#include "Matchers.h"
+#include "Protocol.h"
+#include "SemanticSelection.h"
+#include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+namespace clang {
+namespace clangd {
+namespace {
+using ::testing::ElementsAreArray;
+
+TEST(SemanticSelection, All) {
+  const char *Tests[] = {
+  R"cpp( // Single statement in a function body.
+[[void func() [[{
+  int v = [[1^00;]]
+}
+  )cpp",
+  R"cpp( // Expression
+[[void func() [[{
+  int a = 1;
+  // int v = (10 + 2) * (a + a);
+  int v = (10^]] + 2]])]] * (a + a);]]
+}
+  )cpp",
+  R"cpp( // Function call.
+int add(int x, int y) { return x + y; }
+[[void callee() [[{
+  // int res = add(11, 22);
+  int res = [[add([[1^1]], 22);]]
+}
+  )cpp",
+  R"cpp( // Tricky macros.
+#define MUL ) * (
+[[void func() [[{
+  // int var = (4 + 15 MUL 6 + 10);
+  int var = ([[4 + [[1^5 MUL]] 6 + 10);]]
+}
+   )cpp",
+  R"cpp( // Cursor inside a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HASH(2^3]] + 34]]);]]
+}
+   )cpp",
+  R"cpp( // Cursor on a macro.
+#define HASH(x) ((x) % 10)
+[[void func() [[{
+  int a = [[HA^SH(23);]]
+}
+   )cpp",
+  R"cpp( // Multiple declaration.
+[[void func() [[{
+  int var1, var^2]], var3;]]
+}
+   )cpp",
+  R"cpp( // Before comment.
+[[void func() [[{
+  int var1 = 1;
+  int var2 = var1]]^ /*some comment*/ + 41;]]
+}
+   )cpp",
+  // Empty file.
+  "^",
+  // FIXME: We should get the whole DeclStmt as a range.
+  R"cpp( // Single statement in TU.
+[[int v = [[1^00;
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor at end of VarDecl.
+void func() {
+  int v = 100 + 100^;
+}
+  )cpp",
+  // FIXME: No node found associated to the position.
+  R"cpp( // Cursor in between spaces.
+void func() {
+  int v = 100 + ^  100;
+}
+  )cpp",
+  // Structs.
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = AAA::BBB::c^cc]]();]]
+}
+  )cpp",
+  R"cpp(
+struct AAA { struct BBB { static int ccc(); };};
+[[void func() [[{
+  // int x = AAA::BBB::ccc();
+  int x = [[AA^A]]::]]BBB::]]ccc]]();]]
+}
+  )cpp",
+  R"cpp( // Inside struct.
+struct A { static int a(); };
+[[struct B { 
+  [[static int b() [[{
+[[return 1^1]] + 2;
+  }
+}]];
+  )cpp",
+  // Namespaces.
+  R"cpp( 
+[[namespace nsa { 
+  [[namespace nsb { 
+static int ccc();
+[[void func() [[{
+  // int x = nsa::nsb::ccc();
+  int x = nsa::nsb::cc^c]]();]]
+}
+  }]]
+}]]
+  )cpp",
+
+  };
+
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+auto AST = TestTU::withCode(T.code()).build();
+EXPECT_THAT(llvm::cantFail(getSemanticRanges(AST, T.point())),
+ElementsAreArray(T.ranges()))
+<< Test;
+  }
+}
+} // namespace
+} // namespace clangd
+} // namespace cl

[PATCH] D67358: [clangd] Implement semantic selections.

2019-09-16 Thread UTKARSH SAXENA via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL371976: Implement semantic selections. (authored by 
usaxena95, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D67358?vs=220303&id=220307#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D67358

Files:
  clang-tools-extra/trunk/clangd/CMakeLists.txt
  clang-tools-extra/trunk/clangd/SemanticSelection.cpp
  clang-tools-extra/trunk/clangd/SemanticSelection.h
  clang-tools-extra/trunk/clangd/unittests/CMakeLists.txt
  clang-tools-extra/trunk/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/trunk/clangd/CMakeLists.txt
===
--- clang-tools-extra/trunk/clangd/CMakeLists.txt
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt
@@ -66,6 +66,7 @@
   RIFF.cpp
   Selection.cpp
   SemanticHighlighting.cpp
+  SemanticSelection.cpp
   SourceCode.cpp
   QueryDriverDatabase.cpp
   Threading.cpp
Index: clang-tools-extra/trunk/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticSelection.cpp
+++ clang-tools-extra/trunk/clangd/SemanticSelection.cpp
@@ -0,0 +1,64 @@
+//===--- SemanticSelection.cpp ---*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "SemanticSelection.h"
+#include "ParsedAST.h"
+#include "Protocol.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+// Adds Range \p R to the Result if it is distinct from the last added Range.
+// Assumes that only consecutive ranges can coincide.
+void addIfDistinct(const Range &R, std::vector &Result) {
+  if (Result.empty() || Result.back() != R) {
+Result.push_back(R);
+  }
+}
+} // namespace
+
+llvm::Expected> getSemanticRanges(ParsedAST &AST,
+ Position Pos) {
+  std::vector Result;
+  const auto &SM = AST.getSourceManager();
+  const auto &LangOpts = AST.getASTContext().getLangOpts();
+
+  auto FID = SM.getMainFileID();
+  auto Offset = positionToOffset(SM.getBufferData(FID), Pos);
+  if (!Offset) {
+return Offset.takeError();
+  }
+
+  // Get node under the cursor.
+  SelectionTree ST(AST.getASTContext(), AST.getTokens(), *Offset);
+  for (const auto *Node = ST.commonAncestor(); Node != nullptr;
+   Node = Node->Parent) {
+if (const Decl *D = Node->ASTNode.get()) {
+  if (llvm::isa(D)) {
+break;
+  }
+}
+
+auto SR = toHalfOpenFileRange(SM, LangOpts, Node->ASTNode.getSourceRange());
+if (!SR.hasValue() || SM.getFileID(SR->getBegin()) != SM.getMainFileID()) {
+  continue;
+}
+Range R;
+R.start = sourceLocToPosition(SM, SR->getBegin());
+R.end = sourceLocToPosition(SM, SR->getEnd());
+addIfDistinct(R, Result);
+  }
+  return Result;
+}
+
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/trunk/clangd/SemanticSelection.h
===
--- clang-tools-extra/trunk/clangd/SemanticSelection.h
+++ clang-tools-extra/trunk/clangd/SemanticSelection.h
@@ -0,0 +1,32 @@
+//===--- SemanticSelection.h -*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// Features for giving interesting semantic ranges around the cursor.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICSELECTION_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SEMANTICSELECTION_H
+#include "ParsedAST.h"
+#include "Protocol.h"
+#include "llvm/Support/Error.h"
+#include 
+namespace clang {
+namespace clangd {
+
+/// Returns the list of all interesting ranges around the Position \p Pos.
+/// The interesting ranges corresponds to the AST nodes in the SelectionTree
+/// containing \p Pos.
+/// Any range in the result strictly contains all the previous ranges in the
+/// result. front() is the inner most range. back() is the outermost range.
+llvm::Expected> getSemanticRanges(ParsedAST &AST,
+ Position Pos);
+} // namespace clangd
+} // namespace

[PATCH] D67650: Add SemanticRanges to Clangd server.

2019-09-17 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: hokein.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Adds Semantic Ranges capabilities to Clangd server.
Also adds tests for running it via clangd server.

This differs from the LSP spec as the spec needs this to be evaluated on 
multiple 'pos' and the expected output is an list of list of semantic ranges.
This is majorly for multi cursor and assuming this is a rare thing, we don't 
want to optimize make things complicated just for this. 
This should be done in the LSP level by queueing one request per 'pos' in the 
input.

LSP Spec:
https://github.com/microsoft/language-server-protocol/blob/dbaeumer/3.15/specification.md#textDocument_selectionRange


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67650

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -53,6 +53,9 @@
 SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req);
 RefSlab getRefs(const SymbolIndex &Index, SymbolID ID);
 
+llvm::Expected>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -145,5 +145,12 @@
   return std::move(Slab).build();
 }
 
+llvm::Expected>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos) {
+  llvm::Optional>> Result;
+  Server.semanticRanges(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -7,10 +7,13 @@
 //===--===//
 
 #include "Annotations.h"
+#include "ClangdServer.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "SemanticSelection.h"
 #include "SourceCode.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
 #include "TestTU.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -23,6 +26,11 @@
 namespace {
 using ::testing::ElementsAreArray;
 
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+  std::vector Diagnostics) override {}
+};
+
 TEST(SemanticSelection, All) {
   const char *Tests[] = {
   R"cpp( // Single statement in a function body.
@@ -138,6 +146,39 @@
 << Test;
   }
 }
+
+TEST(SemanticSelection, RunViaClangDServer) {
+  MockFSProvider FS;
+  IgnoreDiagnostics DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooH = testPath("foo.h");
+  const char *HeaderContents =  R"cpp(
+int foo(int x);
+#define HASH(x) ((x) % 10)
+  )cpp";
+  Annotations HeaderAnnotations(HeaderContents);
+  FS.Files[FooH] = HeaderAnnotations.code();
+  Server.addDocument(FooH, HeaderAnnotations.code());
+
+  auto FooCpp = testPath("Foo.cpp");
+  const char *SourceContents = R"cpp(
+  #include "foo.h"
+  [[void bar(int& inp) [[{
+// inp = HASH(foo(inp));
+[[inp = [[HASH([[foo([[in^p]])]]);
+  }
+  )cpp";
+  Annotations SourceAnnotations(SourceContents);
+  FS.Files[FooCpp] = SourceAnnotations.code();
+  Server.addDocument(FooCpp, SourceAnnotations.code());
+
+  auto Ranges = runSemanticRanges(Server, FooCpp, SourceAnnotations.point());
+  ASSERT_TRUE(bool(Ranges))
+  << "getSemanticRange returned an error: " << Ranges.takeError();
+  EXPECT_THAT(*Ranges, ElementsAreArray(SourceAnnotations.ranges()));
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -279,6 +279,10 @@
   void symbolInfo(PathRef File, Position Pos,
   Callback> CB);
 
+  /// Get semantic ranges around a specified position in a file.
+  void semanticRanges(PathRef File, Position Pos,
+  Callback> CB);
+
   /// Returns estimated memory usage for each of the currently open files.
   /// The order of 

[PATCH] D67650: [clangd] Add SemanticRanges to Clangd server.

2019-09-17 Thread UTKARSH SAXENA via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL372102: Add SemanticRanges to Clangd server. (authored by 
usaxena95, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D67650?vs=220465&id=220466#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D67650

Files:
  clang-tools-extra/trunk/clangd/ClangdServer.cpp
  clang-tools-extra/trunk/clangd/ClangdServer.h
  clang-tools-extra/trunk/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/trunk/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/trunk/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp
===
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp
@@ -17,6 +17,7 @@
 #include "Preamble.h"
 #include "Protocol.h"
 #include "SemanticHighlighting.h"
+#include "SemanticSelection.h"
 #include "SourceCode.h"
 #include "TUScheduler.h"
 #include "Trace.h"
@@ -125,8 +126,8 @@
   // critical paths.
   WorkScheduler(
   CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
-  std::make_unique(
-  DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
+  std::make_unique(DynamicIdx.get(), DiagConsumer,
+ Opts.SemanticHighlighting),
   Opts.UpdateDebounce, Opts.RetentionPolicy) {
   // Adds an index to the stack, at higher priority than existing indexes.
   auto AddIndex = [&](SymbolIndex *Idx) {
@@ -620,6 +621,17 @@
   WorkScheduler.runWithAST("SymbolInfo", File, std::move(Action));
 }
 
+void ClangdServer::semanticRanges(PathRef File, Position Pos,
+  Callback> CB) {
+  auto Action =
+  [Pos, CB = std::move(CB)](llvm::Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+CB(clangd::getSemanticRanges(InpAST->AST, Pos));
+  };
+  WorkScheduler.runWithAST("SemanticRanges", File, std::move(Action));
+}
+
 std::vector>
 ClangdServer::getUsedBytesPerFile() const {
   return WorkScheduler.getUsedBytesPerFile();
Index: clang-tools-extra/trunk/clangd/ClangdServer.h
===
--- clang-tools-extra/trunk/clangd/ClangdServer.h
+++ clang-tools-extra/trunk/clangd/ClangdServer.h
@@ -277,6 +277,10 @@
   void symbolInfo(PathRef File, Position Pos,
   Callback> CB);
 
+  /// Get semantic ranges around a specified position in a file.
+  void semanticRanges(PathRef File, Position Pos,
+  Callback> CB);
+
   /// Returns estimated memory usage for each of the currently open files.
   /// The order of results is unspecified.
   /// Overall memory usage of clangd may be significantly more than reported
Index: clang-tools-extra/trunk/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SyncAPI.cpp
@@ -145,5 +145,12 @@
   return std::move(Slab).build();
 }
 
+llvm::Expected>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos) {
+  llvm::Optional>> Result;
+  Server.semanticRanges(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticSelectionTests.cpp
@@ -7,10 +7,13 @@
 //===--===//
 
 #include "Annotations.h"
+#include "ClangdServer.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "SemanticSelection.h"
 #include "SourceCode.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
 #include "TestTU.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -23,6 +26,11 @@
 namespace {
 using ::testing::ElementsAreArray;
 
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+  std::vector Diagnostics) override {}
+};
+
 TEST(SemanticSelection, All) {
   const char *Tests[] = {
   R"cpp( // Single statement in a function body.
@@ -138,6 +146,36 @@
 << Test;
   }
 }
+
+TEST(SemanticSelection, RunViaClangDServer) {
+  MockFSProvider FS;
+  IgnoreDiagnostics DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooH = testPath("foo.h");
+  FS.Files[FooH] = R"cpp(
+int foo(int x);
+#define HASH(x) ((x) % 10)
+  )cpp";
+
+  auto

[PATCH] D67650: [clangd] Add SemanticRanges to Clangd server.

2019-09-17 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220465.
usaxena95 marked 2 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67650

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.cpp
  clang-tools-extra/clangd/unittests/SyncAPI.h

Index: clang-tools-extra/clangd/unittests/SyncAPI.h
===
--- clang-tools-extra/clangd/unittests/SyncAPI.h
+++ clang-tools-extra/clangd/unittests/SyncAPI.h
@@ -53,6 +53,9 @@
 SymbolSlab runFuzzyFind(const SymbolIndex &Index, const FuzzyFindRequest &Req);
 RefSlab getRefs(const SymbolIndex &Index, SymbolID ID);
 
+llvm::Expected>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/unittests/SyncAPI.cpp
===
--- clang-tools-extra/clangd/unittests/SyncAPI.cpp
+++ clang-tools-extra/clangd/unittests/SyncAPI.cpp
@@ -145,5 +145,12 @@
   return std::move(Slab).build();
 }
 
+llvm::Expected>
+runSemanticRanges(ClangdServer &Server, PathRef File, Position Pos) {
+  llvm::Optional>> Result;
+  Server.semanticRanges(File, Pos, capture(Result));
+  return std::move(*Result);
+}
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -7,10 +7,13 @@
 //===--===//
 
 #include "Annotations.h"
+#include "ClangdServer.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "SemanticSelection.h"
 #include "SourceCode.h"
+#include "SyncAPI.h"
+#include "TestFS.h"
 #include "TestTU.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
@@ -23,6 +26,11 @@
 namespace {
 using ::testing::ElementsAreArray;
 
+class IgnoreDiagnostics : public DiagnosticsConsumer {
+  void onDiagnosticsReady(PathRef File,
+  std::vector Diagnostics) override {}
+};
+
 TEST(SemanticSelection, All) {
   const char *Tests[] = {
   R"cpp( // Single statement in a function body.
@@ -138,6 +146,36 @@
 << Test;
   }
 }
+
+TEST(SemanticSelection, RunViaClangDServer) {
+  MockFSProvider FS;
+  IgnoreDiagnostics DiagConsumer;
+  MockCompilationDatabase CDB;
+  ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
+
+  auto FooH = testPath("foo.h");
+  FS.Files[FooH] = R"cpp(
+int foo(int x);
+#define HASH(x) ((x) % 10)
+  )cpp";
+
+  auto FooCpp = testPath("Foo.cpp");
+  const char *SourceContents = R"cpp(
+  #include "foo.h"
+  [[void bar(int& inp) [[{
+// inp = HASH(foo(inp));
+[[inp = [[HASH([[foo([[in^p]])]]);
+  }
+  )cpp";
+  Annotations SourceAnnotations(SourceContents);
+  FS.Files[FooCpp] = SourceAnnotations.code();
+  Server.addDocument(FooCpp, SourceAnnotations.code());
+
+  auto Ranges = runSemanticRanges(Server, FooCpp, SourceAnnotations.point());
+  ASSERT_TRUE(bool(Ranges))
+  << "getSemanticRange returned an error: " << Ranges.takeError();
+  EXPECT_THAT(*Ranges, ElementsAreArray(SourceAnnotations.ranges()));
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -279,6 +279,10 @@
   void symbolInfo(PathRef File, Position Pos,
   Callback> CB);
 
+  /// Get semantic ranges around a specified position in a file.
+  void semanticRanges(PathRef File, Position Pos,
+  Callback> CB);
+
   /// Returns estimated memory usage for each of the currently open files.
   /// The order of results is unspecified.
   /// Overall memory usage of clangd may be significantly more than reported
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -17,6 +17,7 @@
 #include "Preamble.h"
 #include "Protocol.h"
 #include "SemanticHighlighting.h"
+#include "SemanticSelection.h"
 #include "SourceCode.h"
 #include "TUScheduler.h"
 #include "Trace.h"
@@ -125,8 +126,8 @@
   // critical paths.
   WorkScheduler(
   CDB, Opts.AsyncThreadsCount, Opts.StorePreamblesInMemory,
-  std::make_unique(
-  DynamicIdx.get(), DiagConsumer, Opts.SemanticHighlighting),
+  

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: hokein.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

This adds semantic selection to the LSP Server.
Adds support for serialization of input request and the output reply.
Also adds regression tests for the feature.

Currently we do not support multi cursor.The LSP Server only accepts single 
position in the request as opposed to many position in the spec.

Spec:
https://github.com/microsoft/language-server-protocol/blob/dbaeumer/3.15/specification.md#textDocument_selectionRange


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,74 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n int var1;\n int var2 = var1;\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":2,"character":14}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 3
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 0,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 3
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 12,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 17,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 16,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 16,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1222,6 +1222,24 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  // The semantic ranges for a position.
+  // Any range must contain all the previous ranges. ranges.front() must be the
+  // inner most range. ranges.back() must be the outermost range.
+  std::vector ranges;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
=

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220703.
usaxena95 added a comment.

Fixed error message.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,74 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n int var1;\n int var2 = var1;\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":2,"character":14}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 3
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 0,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 3
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 12,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 17,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 16,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 16,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1222,6 +1222,24 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  // The semantic ranges for a position. Any range must contain all the previous
+  // ranges. ranges.front() must be the inner most range. ranges.back() must be
+  // the outermost range.
+  std::vector ranges;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -15,6 +15,7 @@
 #include "URI.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1073,5 +1074,27 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
+  llv

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 220710.
usaxena95 marked 2 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,74 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n int var1;\n int var2 = var1;\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":2,"character":14}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"parent": {
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 3
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 0,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 3
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 12,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 17,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:},
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 16,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 2
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 16,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 2
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1222,6 +1222,24 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  // The semantic ranges for a position. Any range must contain all the previous
+  // ranges. ranges.front() must be the inner most range. ranges.back() must be
+  // the outermost range.
+  std::vector ranges;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -15,6 +15,7 @@
 #include "URI.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1073,5 +1074,27 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/ClangdLSPServer.cpp:1135
+ Params.positions.size());
+Reply(llvm::make_error("failed to decode request",
+ ErrorCode::InvalidRequest));

ilya-biryukov wrote:
> This should be `return Reply(...)`, right?
> Especially bad if `positions` is empty as we attempt to read the first 
> element right away.
Aah. Yeah. Thanks.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720



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


[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 221499.
usaxena95 marked 7 inline comments as done.
usaxena95 added a comment.

Addressed comments:
Added client/server capabilities. 
Made lit test smaller.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 1
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 1
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "referencesProvider": true,
 # CHECK-NEXT:  "renameProvider": true,
+# CHECK-NEXT:  "selectionRangeProvider": true,
 # CHECK-NEXT:  "signatureHelpProvider": {
 # CHECK-NEXT:"triggerCharacters": [
 # CHECK-NEXT:  "(",
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -30,6 +30,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -416,6 +417,10 @@
   /// textDocument.semanticHighlightingCapabilities.semanticHighlighting
   bool SemanticHighlighting = false;
 
+  /// Client supports semantic selection.
+  /// textDocument.selectionRange
+  bool SemanticSelection = false;
+
   /// Supported encodings for LSP character offsets. (clangd extension).
   llvm::Optional> offsetEncoding;
 
@@ -1222,6 +1227,31 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  /**
+   * The [range](#Range) of this selection range.
+   */
+  Range range;
+  /**
+   * The parent selection range containing this range. Therefore `parent.range`
+   * must contain `this.range`.
+   */
+  llvm::Optional> parent;
+
+  SelectionRange() = default;
+  SelectionRange(SelectionRange &&) = default;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -15,6 +15,7 @@
 #include "URI.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -335,6 +336,9 @@
   if (auto RenameSupport = Rename->getBoolean("prepareSupport"))
 R.RenamePrepareSupport = *RenameSupport;
 }
+if (auto *SemanticSelection = TextDocument->get

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

I am not sure adding client capability is useful here. I have not used the 
client capability for selectionRange anywhere and I think we can remove it. 
WDYT ?




Comment at: clang-tools-extra/clangd/ClangdLSPServer.cpp:1131
+Callback> Reply) {
+  if (Params.positions.size() != 1) {
+elog("{0} positions provided to SelectionRange. Supports exactly one "

ilya-biryukov wrote:
> hokein wrote:
> > maybe add an `assert(!Params.positions.empty())`. I think we should not run 
> > into this case.
> But `Params` comes to clangd over LSP, right?
> That means `assert` can fire in case of bad inputs over LSP to clangd.
> Bad inputs over LSP should never crash clangd.
Yes this comes from the client and can be a bad input. We should just return 
error and not crash in such case.



Comment at: clang-tools-extra/clangd/Protocol.h:1241
+llvm::json::Value toJSON(const SelectionRange &);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &, const SelectionRange &);
+

hokein wrote:
> does this operator get used in this patch?
No. Removed it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720



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


[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 221510.
usaxena95 marked 5 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 1
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 1
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "referencesProvider": true,
 # CHECK-NEXT:  "renameProvider": true,
+# CHECK-NEXT:  "selectionRangeProvider": true,
 # CHECK-NEXT:  "signatureHelpProvider": {
 # CHECK-NEXT:"triggerCharacters": [
 # CHECK-NEXT:  "(",
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -30,6 +30,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -416,6 +417,10 @@
   /// textDocument.semanticHighlightingCapabilities.semanticHighlighting
   bool SemanticHighlighting = false;
 
+  /// Client supports semantic selection.
+  /// textDocument.selectionRange
+  bool SemanticSelection = false;
+
   /// Supported encodings for LSP character offsets. (clangd extension).
   llvm::Optional> offsetEncoding;
 
@@ -1222,6 +1227,31 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  /**
+   * The [range](#Range) of this selection range.
+   */
+  Range range;
+  /**
+   * The parent selection range containing this range. Therefore `parent.range`
+   * must contain `this.range`.
+   */
+  llvm::Optional> parent;
+
+  SelectionRange() = default;
+  SelectionRange(SelectionRange &&) = default;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -15,6 +15,7 @@
 #include "URI.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -335,6 +336,9 @@
   if (auto RenameSupport = Rename->getBoolean("prepareSupport"))
 R.RenamePrepareSupport = *RenameSupport;
 }
+if (auto *SemanticSelection = TextDocument->getObject("selectionRange")) {
+  R.SemanticSelection = t

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

> The SelectionRangeClientCapabilities determines what should the LSP server 
> send the client, if it is true, clangd should send 
> SelectionRangeRegistrationOptions. 
>  But looking at the current specification, it doesn't seem to add too much 
> value. I think we can just simplify return a bool for now (as you did in this 
> patch).

Yeah. So should I remove the client capability since we do not use it and just 
return bool as now?




Comment at: clang-tools-extra/clangd/ClangdLSPServer.cpp:1131
+Callback> Reply) {
+  if (Params.positions.size() != 1) {
+elog("{0} positions provided to SelectionRange. Supports exactly one "

hokein wrote:
> usaxena95 wrote:
> > ilya-biryukov wrote:
> > > hokein wrote:
> > > > maybe add an `assert(!Params.positions.empty())`. I think we should not 
> > > > run into this case.
> > > But `Params` comes to clangd over LSP, right?
> > > That means `assert` can fire in case of bad inputs over LSP to clangd.
> > > Bad inputs over LSP should never crash clangd.
> > Yes this comes from the client and can be a bad input. We should just 
> > return error and not crash in such case.
> but the code still doesn't handle the `empty` case?
We do right ?
If the size != 1 then we just return an error.



Comment at: clang-tools-extra/clangd/Protocol.h:1248
+   */
+  llvm::Optional> parent;
+

hokein wrote:
> I think we can simplify the code further, using 
> `llvm::Optional` should be enough, the parent is null for the 
> outer-most range.
I don't think it is possible to do that since the type (SelectionRange) would 
be incomplete at that point. For example size of this class cannot be computed. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720



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


[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 221521.
usaxena95 marked 9 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 1
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 1
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "referencesProvider": true,
 # CHECK-NEXT:  "renameProvider": true,
+# CHECK-NEXT:  "selectionRangeProvider": true,
 # CHECK-NEXT:  "signatureHelpProvider": {
 # CHECK-NEXT:"triggerCharacters": [
 # CHECK-NEXT:  "(",
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -30,6 +30,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -1222,6 +1223,28 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  /**
+   * The range of this selection range.
+   */
+  Range range;
+  /**
+   * The parent selection range containing this range. Therefore `parent.range`
+   * must contain `this.range`.
+   */
+  std::unique_ptr parent;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -15,6 +15,7 @@
 #include "URI.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1073,5 +1074,18 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
+  llvm::json::ObjectMapper O(Params);
+  return O && O.map("textDocument", P.textDocument) &&
+ O.map("positions", P.positions);
+}
+
+llvm::json::Value toJSON(const SelectionRange &Out) {
+  if (Out.parent) {
+return llvm::json::Object{{"range", Out.range},
+  {"parent", toJSON(*Out.parent)}};
+  }
+  return llvm::json::Object{{"range", Out.range}};
+}
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdLSPServer.h
===
--- clang-tools-extra/clangd/ClangdLSPSe

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/ClangdLSPServer.cpp:1169
+Result.emplace_back(render(std::move(*Ranges)));
+return Reply(std::move(Result));
+  });

hokein wrote:
> does `Reply({render(std::move(*Ranges))});` work?
List initialization of vector of move only types is painful 😃 
Even this does not work: 
`Reply(std::vector{render(std::move(*Ranges))});` because I 
think it vector tries to copy construct it because of initializer_lists 



Comment at: clang-tools-extra/clangd/Protocol.h:1251
+  SelectionRange() = default;
+  SelectionRange(SelectionRange &&) = default;
+};

hokein wrote:
> Are these constructors needed?
We don't need them if we use just unique_ptr. They were needed before in 
Optional. Somehow it was not able to deduce this is a 
trivially-constructible + move only class.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720



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


[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 221534.
usaxena95 added a comment.

Removed ununsed header.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/selection-range.test

Index: clang-tools-extra/clangd/test/selection-range.test
===
--- /dev/null
+++ clang-tools-extra/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 1
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 1
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "referencesProvider": true,
 # CHECK-NEXT:  "renameProvider": true,
+# CHECK-NEXT:  "selectionRangeProvider": true,
 # CHECK-NEXT:  "signatureHelpProvider": {
 # CHECK-NEXT:"triggerCharacters": [
 # CHECK-NEXT:  "(",
Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -30,6 +30,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -1222,6 +1223,28 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier textDocument;
+
+  /// The positions inside the text document.
+  std::vector positions;
+};
+bool fromJSON(const llvm::json::Value &, SelectionRangeParams &);
+
+struct SelectionRange {
+  /**
+   * The range of this selection range.
+   */
+  Range range;
+  /**
+   * The parent selection range containing this range. Therefore `parent.range`
+   * must contain `this.range`.
+   */
+  std::unique_ptr parent;
+};
+llvm::json::Value toJSON(const SelectionRange &);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/Protocol.cpp
===
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -1073,5 +1073,18 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
+  llvm::json::ObjectMapper O(Params);
+  return O && O.map("textDocument", P.textDocument) &&
+ O.map("positions", P.positions);
+}
+
+llvm::json::Value toJSON(const SelectionRange &Out) {
+  if (Out.parent) {
+return llvm::json::Object{{"range", Out.range},
+  {"parent", toJSON(*Out.parent)}};
+  }
+  return llvm::json::Object{{"range", Out.range}};
+}
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdLSPServer.h
===
--- clang-tools-extra/clangd/ClangdLSPServer.h
+++ clang-tools-extra/clangd/ClangdLSPServer.h
@@ -107,6 +107,8 @@
   void onChangeConfiguration(const DidChangeConfigurationParams &);
   void onSymbolInfo(const TextDocumentPositionParams &,
 Callback>);
+  void onSelectionRange(const SelectionRangeParam

[PATCH] D67720: [clangd] Add semantic selection to ClangdLSPServer.

2019-09-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL372753: [clangd] Add semantic selection to ClangdLSPServer. 
(authored by usaxena95, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D67720?vs=221534&id=221535#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D67720

Files:
  clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
  clang-tools-extra/trunk/clangd/ClangdLSPServer.h
  clang-tools-extra/trunk/clangd/Protocol.cpp
  clang-tools-extra/trunk/clangd/Protocol.h
  clang-tools-extra/trunk/clangd/test/initialize-params.test
  clang-tools-extra/trunk/clangd/test/selection-range.test

Index: clang-tools-extra/trunk/clangd/ClangdLSPServer.h
===
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h
@@ -107,6 +107,8 @@
   void onChangeConfiguration(const DidChangeConfigurationParams &);
   void onSymbolInfo(const TextDocumentPositionParams &,
 Callback>);
+  void onSelectionRange(const SelectionRangeParams &,
+Callback>);
 
   std::vector getFixes(StringRef File, const clangd::Diagnostic &D);
 
Index: clang-tools-extra/trunk/clangd/Protocol.cpp
===
--- clang-tools-extra/trunk/clangd/Protocol.cpp
+++ clang-tools-extra/trunk/clangd/Protocol.cpp
@@ -1073,5 +1073,18 @@
   };
 }
 
+bool fromJSON(const llvm::json::Value &Params, SelectionRangeParams &P) {
+  llvm::json::ObjectMapper O(Params);
+  return O && O.map("textDocument", P.textDocument) &&
+ O.map("positions", P.positions);
+}
+
+llvm::json::Value toJSON(const SelectionRange &Out) {
+  if (Out.parent) {
+return llvm::json::Object{{"range", Out.range},
+  {"parent", toJSON(*Out.parent)}};
+  }
+  return llvm::json::Object{{"range", Out.range}};
+}
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/trunk/clangd/test/initialize-params.test
===
--- clang-tools-extra/trunk/clangd/test/initialize-params.test
+++ clang-tools-extra/trunk/clangd/test/initialize-params.test
@@ -33,6 +33,7 @@
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "referencesProvider": true,
 # CHECK-NEXT:  "renameProvider": true,
+# CHECK-NEXT:  "selectionRangeProvider": true,
 # CHECK-NEXT:  "signatureHelpProvider": {
 # CHECK-NEXT:"triggerCharacters": [
 # CHECK-NEXT:  "(",
Index: clang-tools-extra/trunk/clangd/test/selection-range.test
===
--- clang-tools-extra/trunk/clangd/test/selection-range.test
+++ clang-tools-extra/trunk/clangd/test/selection-range.test
@@ -0,0 +1,39 @@
+# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void func() {\n}"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/selectionRange","params":{"textDocument":{"uri":"test:///main.cpp"},"positions":[{"line":1,"character":0}]}}
+#  CHECK:  "id": 1
+# CHECK-NEXT:  "jsonrpc": "2.0",
+# CHECK-NEXT:  "result": [
+# CHECK-NEXT:{
+# CHECK-NEXT:  "parent": {
+# CHECK-NEXT:"range": {
+# CHECK-NEXT:  "end": {
+# CHECK-NEXT:"character": 1,
+# CHECK-NEXT:"line": 1
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "start": {
+# CHECK-NEXT:"character": 0,
+# CHECK-NEXT:"line": 0
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  },
+# CHECK-NEXT:  "range": {
+# CHECK-NEXT:"end": {
+# CHECK-NEXT:  "character": 1,
+# CHECK-NEXT:  "line": 1
+# CHECK-NEXT:},
+# CHECK-NEXT:"start": {
+# CHECK-NEXT:  "character": 12,
+# CHECK-NEXT:  "line": 0
+# CHECK-NEXT:}
+# CHECK-NEXT:  }
+# CHECK-NEXT:}
+# CHECK-NEXT:  ]
+# CHECK-NEXT:}
+---
+{"jsonrpc":"2.0","id":3,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
Index: clang-tools-extra/trunk/clangd/Protocol.h
===
--- clang-tools-extra/trunk/clangd/Protocol.h
+++ clang-tools-extra/trunk/clangd/Protocol.h
@@ -30,6 +30,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -1222,6 +1223,28 @@
 };
 llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting);
 
+struct SelectionRangeParams {
+  /// The text document.
+  TextDocumentIdentifier te

[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, mgrang, jkorous, 
MaskRay, ilya-biryukov, mgorny.
Herald added a project: clang.

Removes the 'using namespace' under the cursor and qualifies all accesses in 
the current file.
E.g.:

  using namespace std;
  vector foo(std::map);

Would become:

  std::vector foo(std::map);


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -521,7 +522,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -554,7 +555,6 @@
   EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
   // Don't extract return
   EXPECT_THAT(apply(" if(true) [[return;]] "), StartsWith("fail"));
-  
 }
 
 TEST_F(ExtractFunctionTest, FileTest) {
@@ -648,6 +648,154 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrenc

[PATCH] D68565: [clang] Add test for FindNextToken in Lexer.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: ilya-biryukov.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D68565

Files:
  clang/unittests/Lex/LexerTest.cpp

Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -22,6 +24,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "gtest/gtest.h"
+#include 
 
 using namespace clang;
 
@@ -31,12 +34,9 @@
 class LexerTest : public ::testing::Test {
 protected:
   LexerTest()
-: FileMgr(FileMgrOpts),
-  DiagID(new DiagnosticIDs()),
-  Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
-  SourceMgr(Diags, FileMgr),
-  TargetOpts(new TargetOptions)
-  {
+  : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
 TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
   }
@@ -90,7 +90,7 @@
 bool Invalid;
 StringRef Str =
 Lexer::getSourceText(CharSourceRange::getTokenRange(SourceRange(
-Begin.getLocation(), End.getLocation())),
+ Begin.getLocation(), End.getLocation())),
  SourceMgr, LangOpts, &Invalid);
 if (Invalid)
   return "";
@@ -286,30 +286,31 @@
   CharSourceRange macroRange = SourceMgr.getExpansionRange(lsqrLoc);
 
   SourceLocation Loc;
-  EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
+  EXPECT_TRUE(
+  Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
   EXPECT_EQ(Loc, macroRange.getBegin());
   EXPECT_FALSE(Lexer::isAtStartOfMacroExpansion(idLoc, SourceMgr, LangOpts));
   EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
-  EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
+  EXPECT_TRUE(
+  Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
   EXPECT_EQ(Loc, macroRange.getEnd());
   EXPECT_TRUE(macroRange.isTokenRange());
 
   CharSourceRange range = Lexer::makeFileCharRange(
-   CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
+  CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
   EXPECT_TRUE(range.isInvalid());
-  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(idLoc, rsqrLoc),
-   SourceMgr, LangOpts);
+  range = Lexer::makeFileCharRange(
+  CharSourceRange::getTokenRange(idLoc, rsqrLoc), SourceMgr, LangOpts);
   EXPECT_TRUE(range.isInvalid());
-  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
-   SourceMgr, LangOpts);
+  range = Lexer::makeFileCharRange(
+  CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc), SourceMgr, LangOpts);
   EXPECT_TRUE(!range.isTokenRange());
   EXPECT_EQ(range.getAsRange(),
 SourceRange(macroRange.getBegin(),
 macroRange.getEnd().getLocWithOffset(1)));
 
   StringRef text = Lexer::getSourceText(
-   CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
-   SourceMgr, LangOpts);
+  CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc), SourceMgr, LangOpts);
   EXPECT_EQ(text, "M(foo)");
 
   SourceLocation macroLsqrLoc = toks[3].getLocation();
@@ -320,29 +321,30 @@
   SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
 
   range = Lexer::makeFileCharRange(
-  CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc),
-  SourceMgr, LangOpts);
+  CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc), SourceMgr,
+  LangOpts);
   EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
 range.getAsRange());
 
-  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc),
-   SourceMgr, LangOpts);
+  range = Lexer::makeFileCharRange(
+  CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc), SourceMgr,
+  LangOpts);
   EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
 range.getAsRange());
 
   macroRange = S

[PATCH] D68565: [clang] Add test for FindNextToken in Lexer.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 223503.
usaxena95 added a comment.

Revert unintended formatting.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68565

Files:
  clang/unittests/Lex/LexerTest.cpp


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -22,6 +24,9 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "gtest/gtest.h"
+#include 
+
+namespace {
 
 using namespace clang;
 
@@ -535,4 +540,22 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector ExpectedTokens = {"abcd", "=", "0",";", "int",
+ "xyz",  "=", "abcd", ";"};
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_EQ(ExpectedTokens, GeneratedByNextToken);
+}
 } // anonymous namespace


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -22,6 +24,9 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "gtest/gtest.h"
+#include 
+
+namespace {
 
 using namespace clang;
 
@@ -535,4 +540,22 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector ExpectedTokens = {"abcd", "=", "0",";", "int",
+ "xyz",  "=", "abcd", ";"};
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_EQ(ExpectedTokens, GeneratedByNextToken);
+}
 } // anonymous namespace
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68565: [clang] Add test for FindNextToken in Lexer.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 223524.
usaxena95 marked an inline comment as done.
usaxena95 added a comment.

Addressed comments and fixed build failure.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68565

Files:
  clang/unittests/Lex/LexerTest.cpp


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -21,11 +23,13 @@
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-using namespace clang;
+#include 
 
 namespace {
+using namespace clang;
+using testing::ElementsAre;
 
 // The test fixture.
 class LexerTest : public ::testing::Test {
@@ -535,4 +539,21 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_THAT(GeneratedByNextToken, ElementsAre("abcd", "=", "0", ";", "int",
+"xyz", "=", "abcd", ";"));
+}
 } // anonymous namespace


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -21,11 +23,13 @@
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-using namespace clang;
+#include 
 
 namespace {
+using namespace clang;
+using testing::ElementsAre;
 
 // The test fixture.
 class LexerTest : public ::testing::Test {
@@ -535,4 +539,21 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_THAT(GeneratedByNextToken, ElementsAre("abcd", "=", "0", ";", "int",
+"xyz", "=", "abcd", ";"));
+}
 } // anonymous namespace
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 223592.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

Make the tweak trigger only for TopLevelDecl.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -521,7 +522,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -656,6 +657,160 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+  namespace ns1 { struct vect

[PATCH] D68565: [clang] Add test for FindNextToken in Lexer.

2019-10-07 Thread UTKARSH SAXENA via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGedf5027689c5: [clang] Add test for FindNextToken in Lexer. 
(authored by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68565

Files:
  clang/unittests/Lex/LexerTest.cpp


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -21,11 +23,13 @@
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-using namespace clang;
+#include 
 
 namespace {
+using namespace clang;
+using testing::ElementsAre;
 
 // The test fixture.
 class LexerTest : public ::testing::Test {
@@ -535,4 +539,21 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_THAT(GeneratedByNextToken, ElementsAre("abcd", "=", "0", ";", "int",
+"xyz", "=", "abcd", ";"));
+}
 } // anonymous namespace


Index: clang/unittests/Lex/LexerTest.cpp
===
--- clang/unittests/Lex/LexerTest.cpp
+++ clang/unittests/Lex/LexerTest.cpp
@@ -11,9 +11,11 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/HeaderSearchOptions.h"
 #include "clang/Lex/MacroArgs.h"
@@ -21,11 +23,13 @@
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
-
-using namespace clang;
+#include 
 
 namespace {
+using namespace clang;
+using testing::ElementsAre;
 
 // The test fixture.
 class LexerTest : public ::testing::Test {
@@ -535,4 +539,21 @@
   EXPECT_EQ(Lexer::getSourceText(CR, SourceMgr, LangOpts), "MOO"); // Was "MO".
 }
 
+TEST_F(LexerTest, FindNextToken) {
+  Lex("int abcd = 0;\n"
+  "int xyz = abcd;\n");
+  std::vector GeneratedByNextToken;
+  SourceLocation Loc =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+  while (true) {
+auto T = Lexer::findNextToken(Loc, SourceMgr, LangOpts);
+ASSERT_TRUE(T.hasValue());
+if (T->is(tok::eof))
+  break;
+GeneratedByNextToken.push_back(getSourceText(*T, *T));
+Loc = T->getLocation();
+  }
+  EXPECT_THAT(GeneratedByNextToken, ElementsAre("abcd", "=", "0", ";", "int",
+"xyz", "=", "abcd", ";"));
+}
 } // anonymous namespace
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-08 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 223898.
usaxena95 marked 8 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -521,7 +522,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -656,6 +657,214 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace 

[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-08 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:99
+return false;
+  if (!dyn_cast(TargetDirective->getDeclContext()))
+return false;

ilya-biryukov wrote:
> I believe this check is redundant in presence of `isTopLevelDecl()`...
> (It used to check the 'using namespace' is not inside a function body)
Aah. Makes sense.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:781
+namespace bb { struct map {}; }
+using namespace bb; // Qualifies this.
+  }

ilya-biryukov wrote:
> Argh, this should definitely be fixed :-(
> One simple way to handle this particular only qualify references, which come 
> **after** the first `using namespace` we are removing.
> 
> There's a `SourceManager::isBeforeInTranslationUnit` function that can be 
> used to find out whether something is written before or after a particular 
> point.
> 
> This won't fix all of the cases, but fixing in the general case seems hard.
We also need to qualify the map in such cases.
I have made an attempt to fix this by traversing all the parents namespace decl 
and checking whether they are equal to the concerned namespace.
But this introduces other problems:
```
  namespace aa { namespace bb { struct map {}; }}
  using namespace aa::bb;
  using namespace a^a;
  int main() {
map m;
  }
```
get changed to 
```
  namespace aa { namespace bb { struct map {}; }}
  using namespace aa::bb;
  
  int main() {
aa::map m;
  }
```
Here aa::map is invalid.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562



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


[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-09 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:87
+return false;
+  if (const Decl *ParentDecl = Node->Parent->ASTNode.get())
+return llvm::isa(ParentDecl);

ilya-biryukov wrote:
> Can we use `ASTNode.get()` to directly to check for this?
> 
> Not sure how `DynTypedNode` works, though, maybe that's impossible.
Works for the test. 
The doc for `get` says that it returns NULL if the stored node does not have 
a type that is **convertible** to `T`.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:782
+  int main() {
+aa::map m;
+  }

ilya-biryukov wrote:
> This is incorrect, right? We should not be qualifying here.
> See the relevant comment on `isInsideNamespace`
Works fine now.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562



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


[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-09 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 224038.
usaxena95 marked 5 inline comments as done.
usaxena95 added a comment.

Make action unavailable if the namespace contains a using namespace decl.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -521,7 +522,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -656,6 +657,208 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+ 

[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-09 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 224067.
usaxena95 marked 5 inline comments as done.
usaxena95 added a comment.

Added documentation.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -521,7 +522,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -656,6 +657,208 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace

[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-16 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 225183.
usaxena95 marked 11 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -519,7 +520,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -663,6 +664,222 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace

[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-16 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp:139
+  SourceLocation FirstUsingDirectiveLoc =
+  SM.getLocForEndOfFile(SM.getMainFileID());
+  for (auto *D : AllDirectives) {

ilya-biryukov wrote:
> I'm not 100% certain this is considered to be the end location, as there 
> macros, etc.
> Could we instead start with an invalid source location
Replaced it with uninitialized (which is invalid) SourceLocation. Makes it 
simpler. 



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:810
+  using namespace a::[[b]];
+  using namespace b;
+  int main() { Foo F;}

ilya-biryukov wrote:
> What happens if we remove this one?
> Will it still qualify as `a::b` or as `b::`?
> 
> Could we add a test just to document the behavior?
It qualifies as `b::`. Added a test for it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562



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


[PATCH] D68562: [clangd] Add RemoveUsingNamespace tweak.

2019-10-16 Thread UTKARSH SAXENA via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb62b45412168: [clangd] Add RemoveUsingNamespace tweak. 
(authored by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68562

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/AST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
  clang-tools-extra/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -69,7 +69,8 @@
   EXPECT_EQ(apply("^if (true) {return 100;} else {continue;}"),
 "if (true) {continue;} else {return 100;}");
   EXPECT_EQ(apply("^if () {return 100;} else {continue;}"),
-"if () {continue;} else {return 100;}") << "broken condition";
+"if () {continue;} else {return 100;}")
+  << "broken condition";
   EXPECT_AVAILABLE("^i^f^^(^t^r^u^e^) { return 100; } ^e^l^s^e^ { continue; }");
   EXPECT_UNAVAILABLE("if (true) {^return ^100;^ } else { ^continue^;^ }");
   // Available in subexpressions of the condition;
@@ -100,7 +101,7 @@
   EXPECT_UNAVAILABLE(R"cpp(R"(multi )" ^"token " u8"str\ning")cpp"); // nonascii
   EXPECT_UNAVAILABLE(R"cpp(^R^"^(^multi )" "token " "str\ning")cpp"); // raw
   EXPECT_UNAVAILABLE(R"cpp(^"token\n" __FILE__)cpp"); // chunk is macro
-  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp"); // forbidden escape char
+  EXPECT_UNAVAILABLE(R"cpp(^"a\r\n";)cpp");   // forbidden escape char
 
   const char *Input = R"cpp(R"(multi
 token)" "\nst^ring\n" "literal")cpp";
@@ -286,11 +287,11 @@
  void f(int a) {
int y = PLUS([[1+a]]);
  })cpp",
-  /*FIXME: It should be extracted like this.
-   R"cpp(#define PLUS(x) x++
- void f(int a) {
-   auto dummy = 1+a; int y = PLUS(dummy);
- })cpp"},*/
+   /*FIXME: It should be extracted like this.
+R"cpp(#define PLUS(x) x++
+  void f(int a) {
+auto dummy = 1+a; int y = PLUS(dummy);
+  })cpp"},*/
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = PLUS(1+a); int y = dummy;
@@ -301,13 +302,13 @@
if(1)
 LOOP(5 + [[3]])
  })cpp",
-  /*FIXME: It should be extracted like this. SelectionTree needs to be
-* fixed for macros.
-   R"cpp(#define LOOP(x) while (1) {a = x;}
-   void f(int a) {
- auto dummy = 3; if(1)
-  LOOP(5 + dummy)
-   })cpp"},*/
+   /*FIXME: It should be extracted like this. SelectionTree needs to be
+ * fixed for macros.
+R"cpp(#define LOOP(x) while (1) {a = x;}
+void f(int a) {
+  auto dummy = 3; if(1)
+   LOOP(5 + dummy)
+})cpp"},*/
R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
auto dummy = LOOP(5 + 3); if(1)
@@ -403,8 +404,8 @@
  void f() {
auto dummy = S(2) + S(3) + S(4); S x = S(1) + dummy + S(5);
  })cpp"},
-   // Don't try to analyze across macro boundaries
-   // FIXME: it'd be nice to do this someday (in a safe way)
+  // Don't try to analyze across macro boundaries
+  // FIXME: it'd be nice to do this someday (in a safe way)
   {R"cpp(#define ECHO(X) X
  void f() {
int x = 1 + [[ECHO(2 + 3) + 4]] + 5;
@@ -519,7 +520,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline namespaces
   EXPECT_EQ(apply("au^to x = inl_ns::Visible();"),
-  "Visible x = inl_ns::Visible();");
+"Visible x = inl_ns::Visible();");
   // local class
   EXPECT_EQ(apply("namespace x { void y() { struct S{}; ^auto z = S(); } }"),
 "namespace x { void y() { struct S{}; S z = S(); } }");
@@ -663,6 +664,222 @@
   EXPECT_THAT(apply(" for(;;) { [[while(1) break; break;]] }"),
   StartsWith("fail"));
 }
+
+TWEAK_TEST(RemoveUsingNamespace);
+TEST_F(RemoveUsingNamespaceTest, All) {
+  std::pair Cases[] = {
+  {// Remove all occurrences of ns. Qualify only unqualified.
+   R"cpp(
+  namespace ns1 { struct vector {}; }
+  namespace ns2 { struct map {}; }
+  using namespace n^s1;
+  using namespace ns2;
+  using namespace ns1;
+  int main() {
+ns1::vector v1;
+vector v2;
+map m1;
+  }
+)cpp",
+   R"cpp(
+  namespace ns1 { stru

[PATCH] D69162: [clangd] Remove using-namespace present inside a namespace.

2019-10-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, mgrang, jkorous, 
MaskRay.
Herald added a project: clang.

This patch extends the removing using-namespace code action to remove
using-namespace decl that are present inside a namespace.

Goes over all the references that are declared in `TargetNS` and used in
`ContainingNS`. Removes the current qualifer and qualifies it with only
the `TargetNS`. No other qualifier is needed since it was legal to do
`using namespace TargetNS` in the `ContainingNS`. Therefore all
references inside the `ContainingNS` can be qualified with just
`TargetNS`.

Limitations:

- The using decl must be present in TUDecl or directly under NSDecl.
- Only references inside the DeclContext of using-decl are removed. Any

references outisde this DeclContext are retained as is which is
incorrect.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D69162

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

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -789,15 +789,23 @@
 map m;
   }
 )cpp"},
-  {// Available only for top level namespace decl.
-   R"cpp(
-namespace aa {
-  namespace bb { struct map {}; }
-  using namespace b^b;
-}
-int main() { aa::map m; }
+  {
+  // FIXME: Does not remove usages outside the enclosing NS.
+  R"cpp(
+  namespace aa {
+  namespace bb { struct map {}; }
+  using namespace b^b;
+  }
+  int main() { aa::map m; }
 )cpp",
-   "unavailable"},
+  R"cpp(
+  namespace aa {
+  namespace bb { struct map {}; }
+  
+  }
+  int main() { aa::map m; }
+)cpp",
+  },
   {// FIXME: Unavailable for namespaces containing using-namespace decl.
R"cpp(
   namespace aa {
@@ -875,7 +883,82 @@
   int main() {
 std::vector V;
   }
-)cpp"}};
+)cpp"},
+  {// using inner namespaces.
+   R"cpp(
+  namespace A { namespace B { 
+  inline namespace ns1 { namespace std { struct vector {}; } }
+  using namespace st^d;
+  using namespace A::B::std;
+  using namespace B::std;
+  void func() { 
+vector V1;
+B::vector V2;
+A::B::vector V3;
+A::B::std::vector V4;
+::A::B::std::vector V5;
+::A::B::ns1::std::vector V6;
+  }
+  }}
+)cpp",
+   R"cpp(
+  namespace A { namespace B { 
+  inline namespace ns1 { namespace std { struct vector {}; } }
+  
+  
+  
+  void func() { 
+std::vector V1;
+std::vector V2;
+std::vector V3;
+std::vector V4;
+std::vector V5;
+std::vector V6;
+  }
+  }}
+)cpp"},
+  {// using outer namespaces.
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { 
+  using namespace st^d;
+  void func() { 
+vector V1;
+B::vector V2;
+A::B::vector V3;
+::A::B::vector V4;
+  }
+  }}
+)cpp",
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { 
+  
+  void func() { 
+std::vector V1;
+std::vector V2;
+std::vector V3;
+std::vector V4;
+  }
+  }}
+)cpp"},
+  {// FIXME: No replacements produced for extended namespace.
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { using namespace st^d; }}
+  namespace A { namespace B { int func() { vector V1;}}}
+)cpp",
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B {  }}
+  namespace A { namespace B { int func() { vector V1;}}}
+)cpp"},
+  {// Not available for contexts that are not global or namespaces.
+   R"cpp(
+  namespace std { struct vector {}; }
+  int main() { if(true) { using namespace st^d;}}
+)cpp",
+   "unavailable"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
 }
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -18,6 +18,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 #include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
 #include "llvm/ADT/ScopeExit.h"
+#include 
 
 namespace clang {
 namespace clangd {
@@ -28,9 +29,10 @@
 ///   vector foo(std::map);
 /// Would become:
 ///   std::vector foo(std::map);
-/// Currently limited to using names

[PATCH] D69162: [clangd] Remove using-namespace present inside a namespace.

2019-10-18 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 225596.
usaxena95 added a comment.

Added additional tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69162

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

Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -789,15 +789,23 @@
 map m;
   }
 )cpp"},
-  {// Available only for top level namespace decl.
-   R"cpp(
-namespace aa {
-  namespace bb { struct map {}; }
-  using namespace b^b;
-}
-int main() { aa::map m; }
+  {
+  // FIXME: Does not remove usages outside the enclosing NS.
+  R"cpp(
+  namespace aa {
+  namespace bb { struct map {}; }
+  using namespace b^b;
+  }
+  int main() { aa::map m; }
 )cpp",
-   "unavailable"},
+  R"cpp(
+  namespace aa {
+  namespace bb { struct map {}; }
+  
+  }
+  int main() { aa::map m; }
+)cpp",
+  },
   {// FIXME: Unavailable for namespaces containing using-namespace decl.
R"cpp(
   namespace aa {
@@ -875,7 +883,116 @@
   int main() {
 std::vector V;
   }
-)cpp"}};
+)cpp"},
+  {// using inner namespaces.
+   R"cpp(
+  namespace A { namespace B { 
+  inline namespace ns1 { namespace std { struct vector {}; } }
+  using namespace st^d;
+  using namespace A::B::std;
+  using namespace B::std;
+  void func() { 
+vector V1;
+B::vector V2;
+A::B::vector V3;
+A::B::std::vector V4;
+::A::B::std::vector V5;
+::A::B::ns1::std::vector V6;
+  }
+  }}
+)cpp",
+   R"cpp(
+  namespace A { namespace B { 
+  inline namespace ns1 { namespace std { struct vector {}; } }
+  
+  
+  
+  void func() { 
+std::vector V1;
+std::vector V2;
+std::vector V3;
+std::vector V4;
+std::vector V5;
+std::vector V6;
+  }
+  }}
+)cpp"},
+  {// using outer namespaces.
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { 
+  using namespace st^d;
+  void func() { 
+vector V1;
+B::vector V2;
+A::B::vector V3;
+::A::B::vector V4;
+  }
+  }}
+)cpp",
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { 
+  
+  void func() { 
+std::vector V1;
+std::vector V2;
+std::vector V3;
+std::vector V4;
+  }
+  }}
+)cpp"},
+  {// FIXME: No replacements produced for extended namespace.
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B { using namespace st^d; }}
+  namespace A { namespace B { int func() { vector V1;}}}
+)cpp",
+   R"cpp(
+  namespace std { struct vector {}; }
+  namespace A { namespace B {  }}
+  namespace A { namespace B { int func() { vector V1;}}}
+)cpp"},
+  {// using namespace for outer and inner namespaces: remove inner.
+   R"cpp(
+  namespace out { namespace std { struct vector{}; }}
+  namespace A {
+  using namespace out;
+  using namespace st^d;
+  void func() { vector V;}
+  }
+)cpp",
+   R"cpp(
+  namespace out { namespace std { struct vector{}; }}
+  namespace A {
+  using namespace out;
+  
+  void func() { std::vector V;}
+  }
+)cpp"},
+  {// using namespace for outer and inner namespaces: remove outer.
+   R"cpp(
+  namespace out { namespace std { struct vector{}; }}
+  namespace A {
+  using namespace ou^t;
+  using namespace std;
+  void func() { vector V;}
+  }
+)cpp",
+   R"cpp(
+  namespace out { namespace std { struct vector{}; }}
+  namespace A {
+  
+  using namespace out::std;
+  void func() { vector V;}
+  }
+)cpp"},
+  {// Not available for contexts that are not global or namespaces.
+   R"cpp(
+  namespace std { struct vector {}; }
+  int main() { if(true) { using namespace st^d;}}
+)cpp",
+   "unavailable"}};
   for (auto C : Cases)
 EXPECT_EQ(C.second, apply(C.first)) << C.first;
 }
Index: clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/RemoveUsingNamespace.cpp
@@ -18,6 +18,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 #include "clang/Tooling/Refactoring/RecursiveSymbolVisitor.h"
 #include "llvm/ADT/ScopeExit.

[PATCH] D83814: [clangd] Add Random Forest runtime for code completion.

2020-07-22 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 added a comment.

The features refers to the code completion signals in 
https://github.com/llvm/llvm-project/blob/master/clang-tools-extra/clangd/Quality.h
These signals are currently used to map the code completion candidates to a 
relevance score using hand-coded heuristics. 
We intend to replace the heuristics with a Decision forest model. This patch 
introduces a dummy model and corresponding runtime that will be used to 
inference this model.

This is still WIP and I will provide more details in the description once this 
is finalized.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83814



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


[PATCH] D83814: [clangd] Add Random Forest runtime for code completion.

2020-07-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 280406.
usaxena95 added a comment.

Addressed offline comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83814

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/CompletionModel.cmake
  clang-tools-extra/clangd/CompletionModelCodegen.py
  clang-tools-extra/clangd/for-review-only/CompletionModel.cpp
  clang-tools-extra/clangd/for-review-only/CompletionModel.h
  clang-tools-extra/clangd/for-review-only/DecisionForestRuntimeTest.cpp
  clang-tools-extra/clangd/for-review-only/DecisionForestRuntimeTest.h
  clang-tools-extra/clangd/model/features.json
  clang-tools-extra/clangd/model/forest.json
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
  clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
  clang-tools-extra/clangd/unittests/model/features.json
  clang-tools-extra/clangd/unittests/model/forest.json

Index: clang-tools-extra/clangd/unittests/model/forest.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/forest.json
@@ -0,0 +1,52 @@
+[
+{
+"operation": "if_greater",
+"feature": "ANumber",
+"threshold": 200.0,
+"then": {
+"operation": "if_greater",
+"feature": "AFloat",
+"threshold": -1,
+"then": {
+"operation": "boost",
+"score": 10.0
+},
+"else": {
+"operation": "boost",
+"score": -20.0
+}
+},
+"else": {
+"operation": "if_member",
+"feature": "ACategorical",
+"set": [
+"A",
+"C"
+],
+"then": {
+"operation": "boost",
+"score": 3.0
+},
+"else": {
+"operation": "boost",
+"score": -4.0
+}
+}
+},
+{
+"operation": "if_member",
+"feature": "ACategorical",
+"set": [
+"A",
+"B"
+],
+"then": {
+"operation": "boost",
+"score": 5.0
+},
+"else": {
+"operation": "boost",
+"score": -6.0
+}
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/model/features.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/features.json
@@ -0,0 +1,16 @@
+[
+{
+"name": "ANumber",
+"type": "NUMERICAL"
+},
+{
+"name": "AFloat",
+"type": "NUMERICAL"
+},
+{
+"name": "ACategorical",
+"type": "CATEGORICAL",
+"enum": "ns1::ns2::TestEnum",
+"header": "model/CategoricalFeature.h"
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
@@ -0,0 +1,5 @@
+namespace ns1 {
+namespace ns2 {
+enum TestEnum { A, B, C, D };
+} // namespace ns2
+} // namespace ns1
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
@@ -0,0 +1,30 @@
+
+#include "DecisionForestRuntimeTest.h"
+#include "model/CategoricalFeature.h"
+#include "gtest/gtest.h"
+
+namespace clangd {
+namespace clangd {
+
+TEST(DecisionForestRuntime, Evaluate) {
+  using Example = ::ns1::ns2::test::Example;
+  using Cat = ::ns1::ns2::TestEnum;
+  using ::ns1::ns2::test::Evaluate;
+
+  Example E;
+  E.SetANumber(200); // True
+  E.SetAFloat(0);// True: +10.0
+  E.SetACategorical(Cat::A); // True: +5.0
+  EXPECT_EQ(Evaluate(E), 15.0);
+
+  E.SetANumber(200); // True
+  E.SetAFloat(-2.5); // False: -20.0
+  E.SetACategorical(Cat::B); // True: +5.0
+  EXPECT_EQ(Evaluate(E), -15.0);
+
+  E.SetANumber(100); // False
+  E.SetACategorical(Cat::C); // True: +3.0, False: -6.0
+  EXPECT_EQ(Evaluate(E), -3.0);
+}
+} // namespace clangd
+} // namespace clangd
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,6 +10,7 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
+#include "CompletionModel.h"
 #include "Matchers.h"
 #include "Protocol.h"

[PATCH] D83814: [clangd] Add Random Forest runtime for code completion.

2020-07-24 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 280455.
usaxena95 edited the summary of this revision.
usaxena95 added a comment.

Better formatting in generated files.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D83814

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/CompletionModel.cmake
  clang-tools-extra/clangd/CompletionModelCodegen.py
  clang-tools-extra/clangd/for-review-only/CompletionModel.cpp
  clang-tools-extra/clangd/for-review-only/CompletionModel.h
  clang-tools-extra/clangd/for-review-only/DecisionForestRuntimeTest.cpp
  clang-tools-extra/clangd/for-review-only/DecisionForestRuntimeTest.h
  clang-tools-extra/clangd/model/features.json
  clang-tools-extra/clangd/model/forest.json
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
  clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
  clang-tools-extra/clangd/unittests/model/features.json
  clang-tools-extra/clangd/unittests/model/forest.json

Index: clang-tools-extra/clangd/unittests/model/forest.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/forest.json
@@ -0,0 +1,52 @@
+[
+{
+"operation": "if_greater",
+"feature": "ANumber",
+"threshold": 200.0,
+"then": {
+"operation": "if_greater",
+"feature": "AFloat",
+"threshold": -1,
+"then": {
+"operation": "boost",
+"score": 10.0
+},
+"else": {
+"operation": "boost",
+"score": -20.0
+}
+},
+"else": {
+"operation": "if_member",
+"feature": "ACategorical",
+"set": [
+"A",
+"C"
+],
+"then": {
+"operation": "boost",
+"score": 3.0
+},
+"else": {
+"operation": "boost",
+"score": -4.0
+}
+}
+},
+{
+"operation": "if_member",
+"feature": "ACategorical",
+"set": [
+"A",
+"B"
+],
+"then": {
+"operation": "boost",
+"score": 5.0
+},
+"else": {
+"operation": "boost",
+"score": -6.0
+}
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/model/features.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/features.json
@@ -0,0 +1,16 @@
+[
+{
+"name": "ANumber",
+"type": "NUMERICAL"
+},
+{
+"name": "AFloat",
+"type": "NUMERICAL"
+},
+{
+"name": "ACategorical",
+"type": "CATEGORICAL",
+"enum": "ns1::ns2::TestEnum",
+"header": "model/CategoricalFeature.h"
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/CategoricalFeature.h
@@ -0,0 +1,5 @@
+namespace ns1 {
+namespace ns2 {
+enum TestEnum { A, B, C, D };
+} // namespace ns2
+} // namespace ns1
Index: clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/DecisionForestTests.cpp
@@ -0,0 +1,29 @@
+#include "DecisionForestRuntimeTest.h"
+#include "model/CategoricalFeature.h"
+#include "gtest/gtest.h"
+
+namespace clangd {
+namespace clangd {
+
+TEST(DecisionForestRuntime, Evaluate) {
+  using Example = ::ns1::ns2::test::Example;
+  using Cat = ::ns1::ns2::TestEnum;
+  using ::ns1::ns2::test::Evaluate;
+
+  Example E;
+  E.SetANumber(200); // True
+  E.SetAFloat(0);// True: +10.0
+  E.SetACategorical(Cat::A); // True: +5.0
+  EXPECT_EQ(Evaluate(E), 15.0);
+
+  E.SetANumber(200); // True
+  E.SetAFloat(-2.5); // False: -20.0
+  E.SetACategorical(Cat::B); // True: +5.0
+  EXPECT_EQ(Evaluate(E), -15.0);
+
+  E.SetANumber(100); // False
+  E.SetACategorical(Cat::C); // True: +3.0, False: -6.0
+  EXPECT_EQ(Evaluate(E), -3.0);
+}
+} // namespace clangd
+} // namespace clangd
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,6 +10,7 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
+#include "CompletionModel.h"
 #include "Matchers.h"
 #include "Protocol.h"

[PATCH] D83814: [clangd] Add Random Forest runtime for code completion.

2020-07-14 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov, mgorny.
Herald added a project: clang.

[WIP]

- Proposes a json format for representing Random Forest model.
- Proposes a way to test the generated runtime using a test model.

TODO:

- Add generated source code snippet for easier review.
- Fix unused label warning.
- Figure out required using declarations for CATEGORICAL columns from 
Features.json.
- Necessary Google3 internal modifications for blaze before landing.
- Add documentation for format of the model.
- Document more.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83814

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/CompletionModelCodegen.py
  clang-tools-extra/clangd/model/features.json
  clang-tools-extra/clangd/model/tree.json
  clang-tools-extra/clangd/unittests/CMakeLists.txt
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/model/features.json
  clang-tools-extra/clangd/unittests/model/tree.json

Index: clang-tools-extra/clangd/unittests/model/tree.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/tree.json
@@ -0,0 +1,52 @@
+[
+{
+"operation": "if_greater",
+"feature": "NumReferences",
+"threshold": 200.0,
+"then": {
+"operation": "if_greater",
+"feature": "FileProximityDistance",
+"threshold": -1,
+"then": {
+"operation": "boost",
+"score": 10.0
+},
+"else": {
+"operation": "boost",
+"score": -20.0
+}
+},
+"else": {
+"operation": "if_member",
+"feature": "ContextKind",
+"set": [
+"Kind::CCC_DotMemberAccess",
+"Kind::CCC_ArrowMemberAccess"
+],
+"then": {
+"operation": "boost",
+"score": 3.0
+},
+"else": {
+"operation": "boost",
+"score": -4.0
+}
+}
+},
+{
+"operation": "if_member",
+"feature": "ContextKind",
+"set": [
+"Kind::CCC_Namespace",
+"Kind::CCC_ArrowMemberAccess"
+],
+"then": {
+"operation": "boost",
+"score": 5.0
+},
+"else": {
+"operation": "boost",
+"score": -6.0
+}
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/model/features.json
===
--- /dev/null
+++ clang-tools-extra/clangd/unittests/model/features.json
@@ -0,0 +1,14 @@
+[
+{
+"name": "NumReferences",
+"type": "NUMERICAL"
+},
+{
+"name": "FileProximityDistance",
+"type": "NUMERICAL"
+},
+{
+"name": "ContextKind",
+"type": "CATEGORICAL"
+}
+]
\ No newline at end of file
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -10,6 +10,8 @@
 #include "ClangdServer.h"
 #include "CodeComplete.h"
 #include "Compiler.h"
+#include "CompletionModel.h"
+#include "CompletionModelTest.h"
 #include "Matchers.h"
 #include "Protocol.h"
 #include "Quality.h"
@@ -47,6 +49,7 @@
 using ::testing::IsEmpty;
 using ::testing::Not;
 using ::testing::UnorderedElementsAre;
+using ContextKind = CodeCompletionContext::Kind;
 
 // GMock helpers for matching completion items.
 MATCHER_P(Named, Name, "") { return arg.Name == Name; }
@@ -161,6 +164,36 @@
   return S;
 }
 
+TEST(DecisionForestRuntime, Evaluate) {
+  using Example = clangd::test::Example;
+  using clangd::test::Evaluate;
+
+  Example E;
+  E.SetNumReferences(200);  // True
+  E.SetFileProximityDistance(0);// True: +10.0
+  E.SetContextKind(ContextKind::CCC_ArrowMemberAccess); // True: +5.0
+  EXPECT_EQ(Evaluate(E), 15.0);
+
+  E.SetNumReferences(200);  // True
+  E.SetFileProximityDistance(-2);   // False: -20.0
+  E.SetContextKind(ContextKind::CCC_Namespace); // True: +5.0
+  EXPECT_EQ(Evaluate(E), -15.0);
+
+  E.SetNumReferences(100);// False
+  E.SetContextKind(ContextKind::CCC_DotMemberAccess); // True: +3.0, False: -6.0
+  EXPECT_EQ(Evaluate(E), -3.0);
+}
+
+TEST(DecisionForestRuntime, SanityTest) {
+  using Example = clangd::Example;
+  using clangd::Evaluate;
+  Example E1;
+  E1.SetContextKind(ContextKind::CCC_ArrowMemberAccess);
+  Example E2;
+  E2.SetContextKind(ContextKind::CCC_SymbolOrNewName);
+  EXPECT_GT(Evaluate(E1),

[PATCH] D79500: [clangd] Refactor code completion signal's utility properties.

2020-05-06 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: sammccall.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Current implementation of heuristic-based scoring function also contains
computation of derived signals (e.g. whether name contains a word from
context, computing file distances, scope distances.)
This is an attempt to separate out the logic for computation of derived
signals from the scoring function.
This will allow us to have a clean API for scoring functions that will
take only concrete code completion signals as input.

This only refactors Name and ContextWords which are essentially used to
compute whether the name contains a context word or not. If this looks
good then this will be done for other properties that are more of a
utility (used to compute other signals) than a signal themselves.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D79500

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/FindSymbols.cpp
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/QualityTests.cpp

Index: clang-tools-extra/clangd/unittests/QualityTests.cpp
===
--- clang-tools-extra/clangd/unittests/QualityTests.cpp
+++ clang-tools-extra/clangd/unittests/QualityTests.cpp
@@ -294,13 +294,17 @@
   EXPECT_LT(InBaseClass.evaluate(), Default.evaluate());
 
   llvm::StringSet<> Words = {"one", "two", "three"};
+
   SymbolRelevanceSignals WithoutMatchingWord;
-  WithoutMatchingWord.ContextWords = &Words;
-  WithoutMatchingWord.Name = "four";
+  WithoutMatchingWord.Util.ContextWords = &Words;
+  WithoutMatchingWord.Util.Name = "four";
+  WithoutMatchingWord.calcNameMatchesContext();
   EXPECT_EQ(WithoutMatchingWord.evaluate(), Default.evaluate());
+
   SymbolRelevanceSignals WithMatchingWord;
-  WithMatchingWord.ContextWords = &Words;
-  WithMatchingWord.Name = "TheTwoTowers";
+  WithMatchingWord.Util.ContextWords = &Words;
+  WithMatchingWord.Util.Name = "TheTwoTowers";
+  WithMatchingWord.calcNameMatchesContext();
   EXPECT_GT(WithMatchingWord.evaluate(), Default.evaluate());
 }
 
Index: clang-tools-extra/clangd/XRefs.cpp
===
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -427,7 +427,6 @@
 SymbolQualitySignals Quality;
 Quality.merge(Sym);
 SymbolRelevanceSignals Relevance;
-Relevance.Name = Sym.Name;
 Relevance.Query = SymbolRelevanceSignals::Generic;
 Relevance.merge(Sym);
 auto Score =
Index: clang-tools-extra/clangd/Quality.h
===
--- clang-tools-extra/clangd/Quality.h
+++ clang-tools-extra/clangd/Quality.h
@@ -85,17 +85,18 @@
 
 /// Attributes of a symbol-query pair that affect how much we like it.
 struct SymbolRelevanceSignals {
-  /// The name of the symbol (for ContextWords). Must be explicitly assigned.
-  llvm::StringRef Name;
+  /// Whether name contains some word in context. Must not be set explicitly.
+  /// Computed by calcNameMatchesContext().
+  bool NameMatchesContext = false;
   /// 0-1+ fuzzy-match score for unqualified name. Must be explicitly assigned.
   float NameMatch = 1;
-  /// Lowercase words relevant to the context (e.g. near the completion point).
-  llvm::StringSet<>* ContextWords = nullptr;
+
   bool Forbidden = false; // Unavailable (e.g const) or inaccessible (private).
   /// Whether fixits needs to be applied for that completion or not.
   bool NeedsFixIts = false;
   bool InBaseClass = false; // A member from base class of the accessed class.
 
+  // FIXME: Move this property to utilites.
   URIDistance *FileProximityMatch = nullptr;
   /// These are used to calculate proximity between the index symbol and the
   /// query.
@@ -105,6 +106,7 @@
   /// Proximity between best declaration and the query. [0-1], 1 is closest.
   float SemaFileProximityScore = 0;
 
+  // FIXME: Move this property to utilites.
   // Scope proximity is only considered (both index and sema) when this is set.
   ScopeDistance *ScopeProximityMatch = nullptr;
   llvm::Optional SymbolScope;
@@ -136,6 +138,20 @@
   // Whether the item matches the type expected in the completion context.
   bool TypeMatchesPreferred = false;
 
+  // Properties and utilites used to compute derived signals e.g.
+  // IsNameInContext. These are not directly used by the scoring function.
+  struct Utility {
+/// The name of the symbol (for ContextWords). Must be explicitly assigned.
+llvm::StringRef Name;
+
+/// Lowercase words relevant to the context (e.g. near the completion
+/// point).
+llvm::StringSet<> *ContextWords = nullptr;
+  } Util;
+
+  // Sets NameMatchesContext to true iff Name contains any of the ContextWords.
+  void calcName

[PATCH] D79500: [clangd] Refactor code completion signal's utility properties.

2020-05-08 Thread UTKARSH SAXENA via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 262852.
usaxena95 added a comment.

- Added DerivedSignals struct containing all the derived signals.
- Added NameMatchesContext and proximtiy signals to this struct.
- We need to call computeDerivedSignals() before calling evaluate() if we set 
non-concrete utilites (e.g. ContextWords and Name).
- This is logically equivalent to the previous version (both when the utilites 
are explicitly set and when the default signals are used).
- The utilites are not marked as null in computeDerivedSignals. This is due to 
2 reasons:
  - Current scoring function checks whether `ScopeProximityMatch` is set or not 
to decide whether to multiply with scopeProxitiyScore. Possible solutions:
- Have scopeProxitiyScore as a derived signal itself.
- Or have a different derived signal `HasScopeProximityMatch`.
  - Having these utilities available for debug purposes is great. We can try to 
compute other derived signals (e.g. ContextMatchesName) and test out it's value 
without even adding them concretely to clangd. Once their value is justified, 
we can add it to Quality/Relevance signals.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D79500

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/FindSymbols.cpp
  clang-tools-extra/clangd/Quality.cpp
  clang-tools-extra/clangd/Quality.h
  clang-tools-extra/clangd/Quality.h.rej
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/index/dex/Dex.cpp
  clang-tools-extra/clangd/unittests/QualityTests.cpp

Index: clang-tools-extra/clangd/unittests/QualityTests.cpp
===
--- clang-tools-extra/clangd/unittests/QualityTests.cpp
+++ clang-tools-extra/clangd/unittests/QualityTests.cpp
@@ -268,9 +268,11 @@
   ProxSources.try_emplace(testPath("foo/baz.h"));
   URIDistance Distance(ProxSources);
   IndexProximate.FileProximityMatch = &Distance;
+  IndexProximate.calculateDerivedSignals();
   EXPECT_GT(IndexProximate.evaluate(), Default.evaluate());
   SymbolRelevanceSignals IndexDistant = IndexProximate;
   IndexDistant.SymbolURI = "unittest:/elsewhere/path.h";
+  IndexDistant.calculateDerivedSignals();
   EXPECT_GT(IndexProximate.evaluate(), IndexDistant.evaluate())
   << IndexProximate << IndexDistant;
   EXPECT_GT(IndexDistant.evaluate(), Default.evaluate());
@@ -294,13 +296,17 @@
   EXPECT_LT(InBaseClass.evaluate(), Default.evaluate());
 
   llvm::StringSet<> Words = {"one", "two", "three"};
+
   SymbolRelevanceSignals WithoutMatchingWord;
   WithoutMatchingWord.ContextWords = &Words;
   WithoutMatchingWord.Name = "four";
+  WithoutMatchingWord.calculateDerivedSignals();
   EXPECT_EQ(WithoutMatchingWord.evaluate(), Default.evaluate());
+
   SymbolRelevanceSignals WithMatchingWord;
   WithMatchingWord.ContextWords = &Words;
   WithMatchingWord.Name = "TheTwoTowers";
+  WithMatchingWord.calculateDerivedSignals();
   EXPECT_GT(WithMatchingWord.evaluate(), Default.evaluate());
 }
 
@@ -310,25 +316,31 @@
   Relevance.ScopeProximityMatch = &ScopeProximity;
 
   Relevance.SymbolScope = "other::";
+  Relevance.calculateDerivedSignals();
   float NotMatched = Relevance.evaluate();
 
   Relevance.SymbolScope = "";
+  Relevance.calculateDerivedSignals();
   float Global = Relevance.evaluate();
   EXPECT_GT(Global, NotMatched);
 
   Relevance.SymbolScope = "llvm::";
+  Relevance.calculateDerivedSignals();
   float NonParent = Relevance.evaluate();
   EXPECT_GT(NonParent, Global);
 
   Relevance.SymbolScope = "x::";
+  Relevance.calculateDerivedSignals();
   float GrandParent = Relevance.evaluate();
   EXPECT_GT(GrandParent, Global);
 
   Relevance.SymbolScope = "x::y::";
+  Relevance.calculateDerivedSignals();
   float Parent = Relevance.evaluate();
   EXPECT_GT(Parent, GrandParent);
 
   Relevance.SymbolScope = "x::y::z::";
+  Relevance.calculateDerivedSignals();
   float Enclosing = Relevance.evaluate();
   EXPECT_GT(Enclosing, Parent);
 }
Index: clang-tools-extra/clangd/index/dex/Dex.cpp
===
--- clang-tools-extra/clangd/index/dex/Dex.cpp
+++ clang-tools-extra/clangd/index/dex/Dex.cpp
@@ -126,7 +126,6 @@
   // DistanceCalculator will find the shortest distance from ProximityPaths to
   // any URI extracted from the ProximityPaths.
   URIDistance DistanceCalculator(Sources);
-  PathProximitySignals.FileProximityMatch = &DistanceCalculator;
   // Try to build BOOST iterator for each Proximity Path provided by
   // ProximityPaths. Boosting factor should depend on the distance to the
   // Proximity Path: the closer processed path is, the higher boosting factor.
@@ -134,7 +133,9 @@
 // FIXME(kbobyrev): Append LIMIT on top of every BOOST iterator.
 auto It = iterator(Token(Token::Kind::ProximityURI, ParentURI));
 if (It->kind() != Iterator::Kind::False) {
+  PathProximitySignals.FileProximity

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-29 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456321.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -336,36 +336,98 @@
 ]]};
   )cpp",
   R"cpp(
-[[/* Multi 
+/*[[ Multi 
   * line
   *  comment 
-  */]]
+  ]]*/
   )cpp",
   R"cpp(
-[[// Comment
+//[[ Comment
 // 1]]
 
-[[// Comment
+//[[ Comment
 // 2]]
 
 // No folding for single line comment.
 
-[[/* comment 3
-*/]]
+/*[[ comment 3
+]]*/
 
-[[/* comment 4
-*/]]
+/*[[ comment 4
+]]*/
   )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+a++;]]
+}
+  )cpp",
+  R"cpp(
+// Always exclude last line for brackets.
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else if (a == 2){[[
+a--;]]
+  } else {  // No folding for 2 line bracketed ranges.
+  }]]
+}
+  )cpp",
+  R"cpp(
+/*[[ comment
+* comment]]
+*/
+
+/* No folding for this comment.
+*/
+
+// No folding for this comment.
+
+//[[ 2 single line comment.
+// 2 single line comment.]]
+
+//[[ >=2 line comments.
+// >=2 line comments.
+// >=2 line comments.]]
+
+//[[ foo\
+bar\
+baz]]
+  )cpp",
+  // FIXME: Support folding template arguments.
+  // R"cpp(
+  // template <[[typename foo, class bar]]> struct baz {};
+  // )cpp",
+
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(
+StripColumns(gatherFoldingRanges(llvm::cantFail(
+getFoldingRanges(T.code().str(), /*LineFoldingsOnly=*/true,
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -179,7 +179,7 @@
 // statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
-getFoldingRanges(const std::string &Code) {
+getFoldingRanges(const std::string &Code, bool LineFoldingOnly) {
   aut

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-29 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456335.
usaxena95 marked 3 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -336,36 +336,123 @@
 ]]};
   )cpp",
   R"cpp(
-[[/* Multi 
+/*[[ Multi 
   * line
   *  comment 
-  */]]
+  ]]*/
   )cpp",
   R"cpp(
-[[// Comment
+//[[ Comment
 // 1]]
 
-[[// Comment
+//[[ Comment
 // 2]]
 
 // No folding for single line comment.
 
-[[/* comment 3
-*/]]
+/*[[ comment 3
+]]*/
 
-[[/* comment 4
-*/]]
+/*[[ comment 4
+]]*/
+
+/*[[ foo */
+/* bar ]]*/
+
+/*[[ foo */
+// baz
+/* bar ]]*/
+
+/*[[ foo */
+/* bar*/
+// baz]]
+
+//[[ foo
+/* bar */]]
   )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+a++;]]
+}
+  )cpp",
+  R"cpp(
+// Always exclude last line for brackets.
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else if (a == 2){[[
+a--;]]
+  } else {  // No folding for 2 line bracketed ranges.
+  }]]
+}
+  )cpp",
+  R"cpp(
+/*[[ comment
+* comment]]
+*/
+
+/* No folding for this comment.
+*/
+
+// No folding for this comment.
+
+//[[ 2 single line comment.
+// 2 single line comment.]]
+
+//[[ >=2 line comments.
+// >=2 line comments.
+// >=2 line comments.]]
+
+//[[ foo\
+bar\
+baz]]
+
+/*[[ foo */
+/* bar */]]
+/* baz */
+
+/*[[ foo */
+/* bar]]
+* This does not fold me */
+
+//[[ foo
+/* bar */]]
+  )cpp",
+  // FIXME: Support folding template arguments.
+  // R"cpp(
+  // template <[[typename foo, class bar]]> struct baz {};
+  // )cpp",
+
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(
+StripColumns(gatherFoldingRanges(llvm::cantFail(
+getFoldingRanges(T.code().str(), /*LineFoldingsOnly=*/true,
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-29 Thread Utkarsh Saxena via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa11ec00afea3: FoldingRanges: Handle LineFoldingsOnly 
clients. (authored by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -336,36 +336,123 @@
 ]]};
   )cpp",
   R"cpp(
-[[/* Multi 
+/*[[ Multi 
   * line
   *  comment 
-  */]]
+  ]]*/
   )cpp",
   R"cpp(
-[[// Comment
+//[[ Comment
 // 1]]
 
-[[// Comment
+//[[ Comment
 // 2]]
 
 // No folding for single line comment.
 
-[[/* comment 3
-*/]]
+/*[[ comment 3
+]]*/
 
-[[/* comment 4
-*/]]
+/*[[ comment 4
+]]*/
+
+/*[[ foo */
+/* bar ]]*/
+
+/*[[ foo */
+// baz
+/* bar ]]*/
+
+/*[[ foo */
+/* bar*/
+// baz]]
+
+//[[ foo
+/* bar */]]
   )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+a++;]]
+}
+  )cpp",
+  R"cpp(
+// Always exclude last line for brackets.
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else if (a == 2){[[
+a--;]]
+  } else {  // No folding for 2 line bracketed ranges.
+  }]]
+}
+  )cpp",
+  R"cpp(
+/*[[ comment
+* comment]]
+*/
+
+/* No folding for this comment.
+*/
+
+// No folding for this comment.
+
+//[[ 2 single line comment.
+// 2 single line comment.]]
+
+//[[ >=2 line comments.
+// >=2 line comments.
+// >=2 line comments.]]
+
+//[[ foo\
+bar\
+baz]]
+
+/*[[ foo */
+/* bar */]]
+/* baz */
+
+/*[[ foo */
+/* bar]]
+* This does not fold me */
+
+//[[ foo
+/* bar */]]
+  )cpp",
+  // FIXME: Support folding template arguments.
+  // R"cpp(
+  // template <[[typename foo, class bar]]> struct baz {};
+  // )cpp",
+
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(
+StripColumns(gatherFoldingRanges(llvm::cantFail(
+getFoldingRanges(T.code().str(), /*LineFoldingsOnly=*/true,
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/Seman

[PATCH] D132919: [clangd] Enable folding ranges by default.

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

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132919

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


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -337,7 +337,7 @@
 "folding-ranges",
 cat(Features),
 desc("Enable preview of FoldingRanges feature"),
-init(false),
+init(true),
 Hidden,
 };
 


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -337,7 +337,7 @@
 "folding-ranges",
 cat(Features),
 desc("Enable preview of FoldingRanges feature"),
-init(false),
+init(true),
 Hidden,
 };
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132919: [clangd] Enable folding ranges by default.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456584.
usaxena95 marked an inline comment as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132919

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -308,6 +308,8 @@
 RetiredFlag CrossFileRename("cross-file-rename");
 RetiredFlag ClangTidyChecks("clang-tidy-checks");
 RetiredFlag InlayHints("inlay-hints");
+RetiredFlag FoldingRanges("folding-ranges");
+
 
 opt LimitResults{
 "limit-results",
@@ -333,14 +335,6 @@
 CommaSeparated,
 };
 
-opt FoldingRanges{
-"folding-ranges",
-cat(Features),
-desc("Enable preview of FoldingRanges feature"),
-init(false),
-Hidden,
-};
-
 opt WorkerThreadsCount{
 "j",
 cat(Misc),
@@ -903,7 +897,6 @@
 Opts.StaticIndex = PAI.get();
   }
   Opts.AsyncThreadsCount = WorkerThreadsCount;
-  Opts.FoldingRanges = FoldingRanges;
   Opts.MemoryCleanup = getMemoryCleanupFunction();
 
   Opts.CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -43,6 +43,7 @@
 # CHECK-NEXT:  "clangd.applyTweak"
 # CHECK-NEXT:]
 # CHECK-NEXT:  },
+# CHECK-NEXT:  "foldingRangeProvider": true,
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "implementationProvider": true,
 # CHECK-NEXT:  "inlayHintProvider": true,
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -161,9 +161,6 @@
 /// fetch system include path.
 std::vector QueryDriverGlobs;
 
-/// Enable preview of FoldingRanges feature.
-bool FoldingRanges = false;
-
 // Whether the client supports folding only complete lines.
 bool LineFoldingOnly = false;
 
Index: clang-tools-extra/clangd/ClangdLSPServer.cpp
===
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -584,6 +584,7 @@
   {"callHierarchyProvider", true},
   {"clangdInlayHintsProvider", true},
   {"inlayHintProvider", true},
+  {"foldingRangeProvider", true},
   };
 
   {
@@ -613,8 +614,6 @@
  CodeAction::INFO_KIND}}}
   : llvm::json::Value(true);
 
-  if (Opts.FoldingRanges)
-ServerCaps["foldingRangeProvider"] = true;
 
   std::vector Commands;
   for (llvm::StringRef Command : Handlers.CommandHandlers.keys())
@@ -1618,8 +1617,7 @@
   Bind.method("clangd/inlayHints", this, &ClangdLSPServer::onClangdInlayHints);
   Bind.method("textDocument/inlayHint", this, &ClangdLSPServer::onInlayHint);
   Bind.method("$/memoryUsage", this, &ClangdLSPServer::onMemoryUsage);
-  if (Opts.FoldingRanges)
-Bind.method("textDocument/foldingRange", this, 
&ClangdLSPServer::onFoldingRange);
+  Bind.method("textDocument/foldingRange", this, 
&ClangdLSPServer::onFoldingRange);
   Bind.command(ApplyFixCommand, this, &ClangdLSPServer::onCommandApplyEdit);
   Bind.command(ApplyTweakCommand, this, &ClangdLSPServer::onCommandApplyTweak);
 


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -308,6 +308,8 @@
 RetiredFlag CrossFileRename("cross-file-rename");
 RetiredFlag ClangTidyChecks("clang-tidy-checks");
 RetiredFlag InlayHints("inlay-hints");
+RetiredFlag FoldingRanges("folding-ranges");
+
 
 opt LimitResults{
 "limit-results",
@@ -333,14 +335,6 @@
 CommaSeparated,
 };
 
-opt FoldingRanges{
-"folding-ranges",
-cat(Features),
-desc("Enable preview of FoldingRanges feature"),
-init(false),
-Hidden,
-};
-
 opt WorkerThreadsCount{
 "j",
 cat(Misc),
@@ -903,7 +897,6 @@
 Opts.StaticIndex = PAI.get();
   }
   Opts.AsyncThreadsCount = WorkerThreadsCount;
-  Opts.FoldingRanges = FoldingRanges;
   Opts.MemoryCleanup = getMemoryCleanupFunction();
 
   Opts.CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-param

[PATCH] D132919: [clangd] Enable folding ranges by default.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc33873502003: [clangd] Enable folding ranges by default. 
(authored by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132919

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -308,6 +308,8 @@
 RetiredFlag CrossFileRename("cross-file-rename");
 RetiredFlag ClangTidyChecks("clang-tidy-checks");
 RetiredFlag InlayHints("inlay-hints");
+RetiredFlag FoldingRanges("folding-ranges");
+
 
 opt LimitResults{
 "limit-results",
@@ -333,14 +335,6 @@
 CommaSeparated,
 };
 
-opt FoldingRanges{
-"folding-ranges",
-cat(Features),
-desc("Enable preview of FoldingRanges feature"),
-init(false),
-Hidden,
-};
-
 opt WorkerThreadsCount{
 "j",
 cat(Misc),
@@ -903,7 +897,6 @@
 Opts.StaticIndex = PAI.get();
   }
   Opts.AsyncThreadsCount = WorkerThreadsCount;
-  Opts.FoldingRanges = FoldingRanges;
   Opts.MemoryCleanup = getMemoryCleanupFunction();
 
   Opts.CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
Index: clang-tools-extra/clangd/test/initialize-params.test
===
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -43,6 +43,7 @@
 # CHECK-NEXT:  "clangd.applyTweak"
 # CHECK-NEXT:]
 # CHECK-NEXT:  },
+# CHECK-NEXT:  "foldingRangeProvider": true,
 # CHECK-NEXT:  "hoverProvider": true,
 # CHECK-NEXT:  "implementationProvider": true,
 # CHECK-NEXT:  "inlayHintProvider": true,
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -161,9 +161,6 @@
 /// fetch system include path.
 std::vector QueryDriverGlobs;
 
-/// Enable preview of FoldingRanges feature.
-bool FoldingRanges = false;
-
 // Whether the client supports folding only complete lines.
 bool LineFoldingOnly = false;
 
Index: clang-tools-extra/clangd/ClangdLSPServer.cpp
===
--- clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -584,6 +584,7 @@
   {"callHierarchyProvider", true},
   {"clangdInlayHintsProvider", true},
   {"inlayHintProvider", true},
+  {"foldingRangeProvider", true},
   };
 
   {
@@ -613,8 +614,6 @@
  CodeAction::INFO_KIND}}}
   : llvm::json::Value(true);
 
-  if (Opts.FoldingRanges)
-ServerCaps["foldingRangeProvider"] = true;
 
   std::vector Commands;
   for (llvm::StringRef Command : Handlers.CommandHandlers.keys())
@@ -1618,8 +1617,7 @@
   Bind.method("clangd/inlayHints", this, &ClangdLSPServer::onClangdInlayHints);
   Bind.method("textDocument/inlayHint", this, &ClangdLSPServer::onInlayHint);
   Bind.method("$/memoryUsage", this, &ClangdLSPServer::onMemoryUsage);
-  if (Opts.FoldingRanges)
-Bind.method("textDocument/foldingRange", this, 
&ClangdLSPServer::onFoldingRange);
+  Bind.method("textDocument/foldingRange", this, 
&ClangdLSPServer::onFoldingRange);
   Bind.command(ApplyFixCommand, this, &ClangdLSPServer::onCommandApplyEdit);
   Bind.command(ApplyTweakCommand, this, &ClangdLSPServer::onCommandApplyTweak);
 


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -308,6 +308,8 @@
 RetiredFlag CrossFileRename("cross-file-rename");
 RetiredFlag ClangTidyChecks("clang-tidy-checks");
 RetiredFlag InlayHints("inlay-hints");
+RetiredFlag FoldingRanges("folding-ranges");
+
 
 opt LimitResults{
 "limit-results",
@@ -333,14 +335,6 @@
 CommaSeparated,
 };
 
-opt FoldingRanges{
-"folding-ranges",
-cat(Features),
-desc("Enable preview of FoldingRanges feature"),
-init(false),
-Hidden,
-};
-
 opt WorkerThreadsCount{
 "j",
 cat(Misc),
@@ -903,7 +897,6 @@
 Opts.StaticIndex = PAI.get();
   }
   Opts.AsyncThreadsCount = WorkerThreadsCount;
-  Opts.FoldingRanges = FoldingRanges;
   Opts.MemoryCleanup = getMemoryCleanupFunction();
 
   Opts.CodeComplete.IncludeIneligibleResults = IncludeIneligibleResults;
Index: clang-tools-extra/clangd/test/initialize-params.test
===

[PATCH] D132918: [clang] Fix a crash in constant evaluation

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 accepted this revision.
usaxena95 added a comment.
This revision is now accepted and ready to land.

Thanks. This looks reasonable. 
As discussed offline, this verifiably fixes the crash but it is hard to come up 
with a reduced reproducer.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132918

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


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Fixes: https://github.com/llvm/llvm-project/issues/56183
Fixes: https://github.com/llvm/llvm-project/issues/51695
Fixes: https://github.com/llvm/llvm-project/issues/50455


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp


Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,63 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
\ No newline at end of file
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,7 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; }
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,12 @@
 
 - Correctly set expression evaluation context as 'immediate function context' 
in
   consteval functions.
-  This fixes `GH51182 `
+  This fixes `GH51182 `_.
 
+- Skip re-building lambda expressions when they appear as parameters to an 
immediate invocation.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_.
 
 C++2b Feature Support
 ^


Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,63 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() co

[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456684.
usaxena95 added a comment.

More tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,68 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+template 
+consteval auto bar(F f) { return f;}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  constexpr auto y = bar(bar(bar(bar([]() { return true; }();
+  static_assert(x && y);
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
\ No newline at end of file
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,7 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; }
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,12 @@
 
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
-  This fixes `GH51182 `
+  This fixes `GH51182 `_.
 
+- Skip re-building lambda expressions when they appear as parameters to an immediate invocation.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456685.
usaxena95 added a comment.

new line.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,68 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+template 
+consteval auto bar(F f) { return f;}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  constexpr auto y = bar(bar(bar(bar([]() { return true; }();
+  static_assert(x && y);
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,7 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; }
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,12 @@
 
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
-  This fixes `GH51182 `
+  This fixes `GH51182 `_.
 
+- Skip re-building lambda expressions when they appear as parameters to an immediate invocation.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456739.
usaxena95 added a comment.

Add some test with expected errors as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,77 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 1 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+
+// Reduced 2 
+template 
+consteval auto bar(F f) { return f;}
+
+void test3() {
+  constexpr auto x = bar(bar(bar(bar([]() { return true; }();
+  static_assert(x);
+
+  int a = 1; // expected-note {{declared here}}
+  auto y = bar(bar(bar(bar([=]() { return a; }(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}}
+  // expected-note@-1 {{read of non-const variable 'a' is not allowed in a constant expression}}
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,7 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; }
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,12 @@
 
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
-  This fixes `GH51182 `
+  This fixes `GH51182 `_.
 
+- Skip re-building lambda expressions when they appear as parameters to an immediate invocation.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-08-30 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 456745.
usaxena95 added a comment.

This actually fixes two more issues.
Update release notes and add more documentation.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,77 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 1 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+
+// Reduced 2 
+template 
+consteval auto bar(F f) { return f;}
+
+void test3() {
+  constexpr auto x = bar(bar(bar(bar([]() { return true; }();
+  static_assert(x);
+
+  int a = 1; // expected-note {{declared here}}
+  auto y = bar(bar(bar(bar([=]() { return a; }(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}}
+  // expected-note@-1 {{read of non-const variable 'a' is not allowed in a constant expression}}
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,11 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) {
+  // Lambdas must be built already. They must not be re-built as it always
+  // creates new types.
+  return E;
+}
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,14 @@
 
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
-  This fixes `GH51182 `
-
+  This fixes `GH51182 `_.
+
+- Skip re-building lambda expressions when they appear as parameters to an immediate invocation.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_,
+  `GH54872 `_,
+  `GH54587 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-09-01 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 added a comment.

Gentle ping for review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

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


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-09-02 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 457546.
usaxena95 marked 2 inline comments as done.
usaxena95 added a comment.

Addressed comments and added more tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,82 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 1 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+
+// Reduced 2 
+template 
+consteval auto bar(F f) { return f;}
+
+void test3() {
+  constexpr auto t1 = bar(bar(bar(bar([]() { return true; }();
+  static_assert(t1);
+
+  int a = 1; // expected-note {{declared here}}
+  auto t2 = bar(bar(bar(bar([=]() { return a; }(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}}
+  // expected-note@-1 {{read of non-const variable 'a' is not allowed in a constant expression}}
+
+  constexpr auto t3 = bar(bar([x=bar(42)]() { return x; }))();
+  static_assert(t3==42);
+  constexpr auto t4 = bar(bar([x=bar(42)]() consteval { return x; }))();
+  static_assert(t4==42);
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,11 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) {
+  // Do not rebuild lambdas to avoid creating a new type.
+  // Lambdas have already been processed inside their eval context.
+  return E;
+}
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -191,8 +191,14 @@
 
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
-  This fixes `GH51182 `
-
+  This fixes `GH51182 `_.
+
+- Skip rebuilding lambda expressions in arguments of immediate invocations.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_,
+  `GH54872 `_,
+  `GH54587 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132945: [clang] Skip re-building lambda expressions in parameters to consteval fns.

2022-09-02 Thread Utkarsh Saxena via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe7eec3824656: [clang] Skip re-building lambda expressions in 
parameters to consteval fns. (authored by usaxena95).

Changed prior to commit:
  https://reviews.llvm.org/D132945?vs=457546&id=457555#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D132945

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,82 @@
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original 
+template 
+struct type_t {};
+
+template 
+struct list_t {};
+
+template 
+consteval auto pop_front(list_t) -> auto {
+  return list_t{};
+}
+
+template 
+consteval auto apply(list_t, F fn) -> auto {
+  return fn(type_t{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t{}),
+[](type_t...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 1 
+consteval bool zero() { return false; }
+
+template 
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+
+// Reduced 2 
+template 
+consteval auto bar(F f) { return f;}
+
+void test3() {
+  constexpr auto t1 = bar(bar(bar(bar([]() { return true; }();
+  static_assert(t1);
+
+  int a = 1; // expected-note {{declared here}}
+  auto t2 = bar(bar(bar(bar([=]() { return a; }(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}}
+  // expected-note@-1 {{read of non-const variable 'a' is not allowed in a constant expression}}
+
+  constexpr auto t3 = bar(bar([x=bar(42)]() { return x; }))();
+  static_assert(t3==42);
+  constexpr auto t4 = bar(bar([x=bar(42)]() consteval { return x; }))();
+  static_assert(t4==42);
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,11 @@
   DRSet.erase(E);
   return E;
 }
+ExprResult TransformLambdaExpr(LambdaExpr *E) {
+  // Do not rebuild lambdas to avoid creating a new type.
+  // Lambdas have already been processed inside their eval context.
+  return E;
+}
 bool AlwaysRebuild() { return false; }
 bool ReplacingOriginal() { return true; }
 bool AllowSkippingCXXConstructExpr() {
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -211,9 +211,16 @@
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
   This fixes `GH51182 `
+
 - Fixes an assert crash caused by looking up missing vtable information on ``consteval``
   virtual functions. Fixes `GH55065 `_.
 
+- Skip rebuilding lambda expressions in arguments of immediate invocations.
+  This fixes `GH56183 `_,
+  `GH51695 `_,
+  `GH50455 `_,
+  `GH54872 `_,
+  `GH54587 `_.
 
 C++2b Feature Support
 ^
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133299: [clangd] Fix LineFoldingOnly flag is not propagated correctly to ClangdServer.

2022-09-05 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 accepted this revision.
usaxena95 added a comment.
This revision is now accepted and ready to land.

Thanks. Sorry I missed this.




Comment at: clang-tools-extra/clangd/ClangdLSPServer.cpp:487-497
   {
 // Switch caller's context with LSPServer's background context. Since we
 // rather want to propagate information from LSPServer's context into the
 // Server, CDB, etc.
 WithContext MainContext(BackgroundContext.clone());
 llvm::Optional WithOffsetEncoding;
 if (Opts.Encoding)

I think we should do this after the Opts has been fully set to avoid the 
confusion


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133299

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


[PATCH] D130081: Add foldings for multi-line comment.

2022-07-26 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 447926.
usaxena95 marked 4 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130081

Files:
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -335,6 +335,27 @@
   ]]}   \
 ]]};
   )cpp",
+  R"cpp(
+[[/* Multi 
+  * line
+  *  comment 
+  */]]
+  )cpp",
+  R"cpp(
+[[// Comment
+// 1]]
+
+[[// Comment
+// 2]]
+
+// No folding for single line comment.
+
+[[/* comment 3
+*/]]
+
+[[/* comment 4
+*/]]
+  )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -22,6 +22,7 @@
 #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
 #include "clang/Tooling/Syntax/Tree.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Error.h"
 #include 
@@ -173,16 +174,16 @@
   return collectFoldingRanges(SyntaxTree, TM);
 }
 
-// FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and
-// other code regions (e.g. public/private/protected sections of classes,
-// control flow statement bodies).
+// FIXME( usaxena95): Collect PP conditional regions, includes and other code
+// regions (e.g. public/private/protected sections of classes, control flow
+// statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
 getFoldingRanges(const std::string &Code) {
-  auto OrigStream = clang::pseudo::lex(Code, clang::pseudo::genericLangOpts());
+  auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
-  auto DirectiveStructure = clang::pseudo::DirectiveTree::parse(OrigStream);
-  clang::pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
+  auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
+  pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
 
   // FIXME: Provide ranges in the disabled-PP regions as well.
   auto Preprocessed = DirectiveStructure.stripDirectives(OrigStream);
@@ -191,26 +192,58 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  for (const auto &Tok : ParseableStream.tokens()) {
+  auto ToFoldingRange = [](Position Start, Position End,
+   llvm::StringLiteral Kind) {
+FoldingRange FR;
+FR.startLine = Start.line;
+FR.startCharacter = Start.character;
+FR.endLine = End.line;
+FR.endCharacter = End.character;
+FR.kind = Kind.str();
+return FR;
+  };
+  auto OriginalToken = [&](const pseudo::Token &T) {
+return OrigStream.tokens()[T.OriginalIndex];
+  };
+  auto StartOffset = [&](const pseudo::Token &T) {
+return OriginalToken(T).text().data() - Code.data();
+  };
+  auto StartPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T));
+  };
+  auto EndPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T) + OriginalToken(T).Length);
+  };
+  auto Tokens = ParseableStream.tokens();
+  // Brackets.
+  for (const auto &Tok : Tokens) {
 if (auto *Paired = Tok.pair()) {
   // Process only token at the start of the range. Avoid ranges on a single
   // line.
   if (Tok.Line < Paired->Line) {
-Position Start = offsetToPosition(
-Code,
-OrigStream.tokens()[Tok.OriginalIndex].text().data() - Code.data());
-Position End = offsetToPosition(
-Code, OrigStream.tokens()[Paired->OriginalIndex].text().data() -
-  Code.data());
-FoldingRange FR;
-FR.startLine = Start.line;
-FR.startCharacter = Start.character + 1;
-FR.endLine = End.line;
-FR.endCharacter = End.character;
-Result.push_back(FR);
+Position Start = offsetToPosition(Code, 1 + StartOffset(Tok));
+Position End = offsetToPosition(Code, StartOffset(*Paired));
+Result.push_back(ToFoldingRange(Start, End, FoldingRange::REGION_KIND));
   }
 }
   }
+  // Multi-line comments.
+  for (const auto *T = Tokens.begin(); T != Tokens.end();) {
+if (T->Kind != tok::comment) {
+  

[PATCH] D130081: Add foldings for multi-line comment.

2022-07-26 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/SemanticSelection.cpp:232
+while (T != Tokens.end() && T->Kind == tok::comment &&
+   LastComment->Line == T->Line + 1) {
+  LastComment = T;

hokein wrote:
> this seems incorrect -- the ` LastComment->Line == T->Line + 1` condition is 
> not true initially (because `LastComment == T`), so we will never run into 
> this loop, then I'm confused, why the unittest are passed (premerge test is 
> green).
I think I missed to update the patch last time I fixed this.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130081

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


[PATCH] D130081: Add foldings for multi-line comment.

2022-07-26 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 447928.
usaxena95 added a comment.

Remove unintended changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130081

Files:
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -335,6 +335,27 @@
   ]]}   \
 ]]};
   )cpp",
+  R"cpp(
+[[/* Multi 
+  * line
+  *  comment 
+  */]]
+  )cpp",
+  R"cpp(
+[[// Comment
+// 1]]
+
+[[// Comment
+// 2]]
+
+// No folding for single line comment.
+
+[[/* comment 3
+*/]]
+
+[[/* comment 4
+*/]]
+  )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -22,6 +22,7 @@
 #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
 #include "clang/Tooling/Syntax/Tree.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Error.h"
 #include 
@@ -173,16 +174,16 @@
   return collectFoldingRanges(SyntaxTree, TM);
 }
 
-// FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and
-// other code regions (e.g. public/private/protected sections of classes,
-// control flow statement bodies).
+// FIXME( usaxena95): Collect PP conditional regions, includes and other code
+// regions (e.g. public/private/protected sections of classes, control flow
+// statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
 getFoldingRanges(const std::string &Code) {
-  auto OrigStream = clang::pseudo::lex(Code, clang::pseudo::genericLangOpts());
+  auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
-  auto DirectiveStructure = clang::pseudo::DirectiveTree::parse(OrigStream);
-  clang::pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
+  auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
+  pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
 
   // FIXME: Provide ranges in the disabled-PP regions as well.
   auto Preprocessed = DirectiveStructure.stripDirectives(OrigStream);
@@ -191,26 +192,58 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  for (const auto &Tok : ParseableStream.tokens()) {
+  auto ToFoldingRange = [](Position Start, Position End,
+   llvm::StringLiteral Kind) {
+FoldingRange FR;
+FR.startLine = Start.line;
+FR.startCharacter = Start.character;
+FR.endLine = End.line;
+FR.endCharacter = End.character;
+FR.kind = Kind.str();
+return FR;
+  };
+  auto OriginalToken = [&](const pseudo::Token &T) {
+return OrigStream.tokens()[T.OriginalIndex];
+  };
+  auto StartOffset = [&](const pseudo::Token &T) {
+return OriginalToken(T).text().data() - Code.data();
+  };
+  auto StartPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T));
+  };
+  auto EndPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T) + OriginalToken(T).Length);
+  };
+  auto Tokens = ParseableStream.tokens();
+  // Brackets.
+  for (const auto &Tok : Tokens) {
 if (auto *Paired = Tok.pair()) {
   // Process only token at the start of the range. Avoid ranges on a single
   // line.
   if (Tok.Line < Paired->Line) {
-Position Start = offsetToPosition(
-Code,
-OrigStream.tokens()[Tok.OriginalIndex].text().data() - Code.data());
-Position End = offsetToPosition(
-Code, OrigStream.tokens()[Paired->OriginalIndex].text().data() -
-  Code.data());
-FoldingRange FR;
-FR.startLine = Start.line;
-FR.startCharacter = Start.character + 1;
-FR.endLine = End.line;
-FR.endCharacter = End.character;
-Result.push_back(FR);
+Position Start = offsetToPosition(Code, 1 + StartOffset(Tok));
+Position End = StartPosition(*Paired);
+Result.push_back(ToFoldingRange(Start, End, FoldingRange::REGION_KIND));
   }
 }
   }
+  // Multi-line comments.
+  for (const auto *T = Tokens.begin(); T != Tokens.end();) {
+if (T->Kind != tok::comment) {
+  T++;
+  continue;
+}
+Position Start = Star

[PATCH] D130011: Use pseudoparser-based folding ranges in ClangdServer.

2022-07-27 Thread Utkarsh Saxena via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdf537bef6393: Use pseudoparser-based folding ranges in 
ClangdServer. (authored by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130011

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


Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -834,14 +834,17 @@
 
 void ClangdServer::foldingRanges(llvm::StringRef File,
  Callback> CB) {
-  auto Action =
-  [CB = std::move(CB)](llvm::Expected InpAST) mutable {
-if (!InpAST)
-  return CB(InpAST.takeError());
-CB(clangd::getFoldingRanges(InpAST->AST));
-  };
-  WorkScheduler->runWithAST("FoldingRanges", File, std::move(Action),
-Transient);
+  auto Code = getDraft(File);
+  if (!Code)
+return CB(llvm::make_error(
+"trying to compute folding ranges for non-added document",
+ErrorCode::InvalidParams));
+  auto Action = [CB = std::move(CB), Code = std::move(*Code)]() mutable {
+CB(clangd::getFoldingRanges(Code));
+  };
+  // We want to make sure folding ranges are always available for all the open
+  // files, hence prefer runQuick to not wait for operations on other files.
+  WorkScheduler->runQuick("FoldingRanges", File, std::move(Action));
 }
 
 void ClangdServer::findType(llvm::StringRef File, Position Pos,


Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -834,14 +834,17 @@
 
 void ClangdServer::foldingRanges(llvm::StringRef File,
  Callback> CB) {
-  auto Action =
-  [CB = std::move(CB)](llvm::Expected InpAST) mutable {
-if (!InpAST)
-  return CB(InpAST.takeError());
-CB(clangd::getFoldingRanges(InpAST->AST));
-  };
-  WorkScheduler->runWithAST("FoldingRanges", File, std::move(Action),
-Transient);
+  auto Code = getDraft(File);
+  if (!Code)
+return CB(llvm::make_error(
+"trying to compute folding ranges for non-added document",
+ErrorCode::InvalidParams));
+  auto Action = [CB = std::move(CB), Code = std::move(*Code)]() mutable {
+CB(clangd::getFoldingRanges(Code));
+  };
+  // We want to make sure folding ranges are always available for all the open
+  // files, hence prefer runQuick to not wait for operations on other files.
+  WorkScheduler->runQuick("FoldingRanges", File, std::move(Action));
 }
 
 void ClangdServer::findType(llvm::StringRef File, Position Pos,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130081: Add foldings for multi-line comment.

2022-08-02 Thread Utkarsh Saxena via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9ef11616b228: Add foldings for multi-line comment. (authored 
by usaxena95).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130081

Files:
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -335,6 +335,27 @@
   ]]}   \
 ]]};
   )cpp",
+  R"cpp(
+[[/* Multi 
+  * line
+  *  comment 
+  */]]
+  )cpp",
+  R"cpp(
+[[// Comment
+// 1]]
+
+[[// Comment
+// 2]]
+
+// No folding for single line comment.
+
+[[/* comment 3
+*/]]
+
+[[/* comment 4
+*/]]
+  )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -22,6 +22,7 @@
 #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
 #include "clang/Tooling/Syntax/Tree.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Error.h"
 #include 
@@ -173,16 +174,16 @@
   return collectFoldingRanges(SyntaxTree, TM);
 }
 
-// FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and
-// other code regions (e.g. public/private/protected sections of classes,
-// control flow statement bodies).
+// FIXME( usaxena95): Collect PP conditional regions, includes and other code
+// regions (e.g. public/private/protected sections of classes, control flow
+// statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
 getFoldingRanges(const std::string &Code) {
-  auto OrigStream = clang::pseudo::lex(Code, clang::pseudo::genericLangOpts());
+  auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
-  auto DirectiveStructure = clang::pseudo::DirectiveTree::parse(OrigStream);
-  clang::pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
+  auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
+  pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
 
   // FIXME: Provide ranges in the disabled-PP regions as well.
   auto Preprocessed = DirectiveStructure.stripDirectives(OrigStream);
@@ -191,26 +192,58 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  for (const auto &Tok : ParseableStream.tokens()) {
+  auto ToFoldingRange = [](Position Start, Position End,
+   llvm::StringLiteral Kind) {
+FoldingRange FR;
+FR.startLine = Start.line;
+FR.startCharacter = Start.character;
+FR.endLine = End.line;
+FR.endCharacter = End.character;
+FR.kind = Kind.str();
+return FR;
+  };
+  auto OriginalToken = [&](const pseudo::Token &T) {
+return OrigStream.tokens()[T.OriginalIndex];
+  };
+  auto StartOffset = [&](const pseudo::Token &T) {
+return OriginalToken(T).text().data() - Code.data();
+  };
+  auto StartPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T));
+  };
+  auto EndPosition = [&](const pseudo::Token &T) {
+return offsetToPosition(Code, StartOffset(T) + OriginalToken(T).Length);
+  };
+  auto Tokens = ParseableStream.tokens();
+  // Brackets.
+  for (const auto &Tok : Tokens) {
 if (auto *Paired = Tok.pair()) {
   // Process only token at the start of the range. Avoid ranges on a single
   // line.
   if (Tok.Line < Paired->Line) {
-Position Start = offsetToPosition(
-Code,
-OrigStream.tokens()[Tok.OriginalIndex].text().data() - Code.data());
-Position End = offsetToPosition(
-Code, OrigStream.tokens()[Paired->OriginalIndex].text().data() -
-  Code.data());
-FoldingRange FR;
-FR.startLine = Start.line;
-FR.startCharacter = Start.character + 1;
-FR.endLine = End.line;
-FR.endCharacter = End.character;
-Result.push_back(FR);
+Position Start = offsetToPosition(Code, 1 + StartOffset(Tok));
+Position End = StartPosition(*Paired);
+Result.push_back(ToFoldingRange(Start, End, FoldingRange::REGION_KIND));
   }
 }
   }
+  // Multi-line comments.
+  for (const auto *T = Tokens.begin(); T != Tokens.end();) {
+if (T->Kind != tok::comment

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-04 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 created this revision.
usaxena95 added a reviewer: hokein.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Do not fold the endline which contains tokens after the end of range.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -359,13 +359,44 @@
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else {[[
+a--;
+  ]]}
+  if(a == 1) {[[
+a++;]]
+  } // A token on the end line.
+]]}
+  )cpp",
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/true))),
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -179,7 +179,7 @@
 // statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
-getFoldingRanges(const std::string &Code) {
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly) {
   auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
   auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
@@ -192,15 +192,21 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  auto ToFoldingRange = [](Position Start, Position End,
-   llvm::StringLiteral Kind) {
+  auto AddFoldingRange = [&](Position Start, Position End,
+ llvm::StringLiteral Kind) {
+if (Start.line >= End.line)
+  return;
 FoldingRange FR;
 FR.startLine = Start.line;
-FR.startCharacter = Start.character;
 FR.endLine = End.line;
-FR.endCharacter = End.character;
+if (LineFoldingsOnly)
+  FR.startCharacter = FR.endCharacter = 0;
+else {
+  FR.startCharacter = Start.character;
+  FR.endCharacter = End.character;
+}
 FR.kind = Kind.str();
-return FR;
+Result.push_back(FR);
   };
   auto OriginalToken = [&](const pseudo::Token &T) {
 return OrigStream.tokens()[T.OriginalIndex];
@@ -221,9 +227,16 @@
  

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-04 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 449928.
usaxena95 added a comment.

Do same for multi-line comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -359,13 +359,52 @@
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else {[[
+a--;
+  /*tokens inside foldings are fine.*/ ]]}
+]]}
+  )cpp",
+  R"cpp(
+void func(int a) {[[
+a++;]]
+} // A token on the end line.
+  )cpp",
+  R"cpp(
+[[/* comment 1
+* comment 1]]
+*/ int a_token = 0;
+  )cpp",
+
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/true))),
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -179,7 +179,7 @@
 // statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
-getFoldingRanges(const std::string &Code) {
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly) {
   auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
   auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
@@ -192,15 +192,21 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  auto ToFoldingRange = [](Position Start, Position End,
-   llvm::StringLiteral Kind) {
+  auto AddFoldingRange = [&](Position Start, Position End,
+ llvm::StringLiteral Kind) {
+if (Start.line >= End.line)
+  return;
 FoldingRange FR;
 FR.startLine = Start.line;
-FR.startCharacter = Start.character;
 FR.endLine = End.line;
-FR.endCharacter = End.character;
+if (LineFoldingsOnly)
+  FR.startCharacter = FR.endCharacter = 0;
+else {
+  FR.startCharacter = Start.character;
+  FR.endCharacter = End.character;
+}
 FR.kind = Kind.str();
-return FR;
+Result.push_back(FR);
   };
   auto OriginalToken = [&](const pseudo::Token &T) {
 return OrigStream.tokens()[T.OriginalIndex];
@@ -214,6 +220,17

[PATCH] D131154: FoldingRanges: Handle LineFoldingsOnly clients.

2022-08-04 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 449931.
usaxena95 added a comment.

More tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131154

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.cpp
  clang-tools-extra/clangd/Protocol.h
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -196,7 +196,7 @@
   ElementsAre(SourceAnnotations.range("empty")));
 }
 
-TEST(FoldingRanges, All) {
+TEST(FoldingRanges, ASTAll) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -265,7 +265,7 @@
   }
 }
 
-TEST(FoldingRangesPseudoParser, All) {
+TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
   const char *Tests[] = {
   R"cpp(
 #define FOO int foo() {\
@@ -359,13 +359,55 @@
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-EXPECT_THAT(
-gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/false))),
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
 
+TEST(FoldingRanges, PseudoParserLineFoldingsOnly) {
+  const char *Tests[] = {
+  R"cpp(
+void func(int a) {[[
+  if(a == 1) {[[
+a++;]]
+  } else {[[
+a--;
+  /*tokens inside foldings are fine.*/ ]]}
+]]}
+  )cpp",
+  R"cpp(
+void func(int a) {[[
+a++;]]
+} // A token on the end line.
+  )cpp",
+  R"cpp(
+[[/* comment 1
+* comment 1]]
+*/ int a_token = 0;
+
+/* No folding for this comment.
+*/ int b_token=0;
+  )cpp",
+
+  };
+  auto StripColumns = [](const std::vector &Ranges) {
+std::vector Res;
+for (Range R : Ranges) {
+  R.start.character = R.end.character = 0;
+  Res.push_back(R);
+}
+return Res;
+  };
+  for (const char *Test : Tests) {
+auto T = Annotations(Test);
+EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(
+T.code().str(), /*LineFoldingsOnly=*/true))),
+UnorderedElementsAreArray(StripColumns(T.ranges(
+<< Test;
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -33,7 +33,7 @@
 /// Returns a list of ranges whose contents might be collapsible in an editor.
 /// This version uses the pseudoparser which does not require the AST.
 llvm::Expected>
-getFoldingRanges(const std::string &Code);
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly);
 
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -179,7 +179,7 @@
 // statement bodies).
 // Related issue: https://github.com/clangd/clangd/issues/310
 llvm::Expected>
-getFoldingRanges(const std::string &Code) {
+getFoldingRanges(const std::string &Code, bool LineFoldingsOnly) {
   auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
 
   auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
@@ -192,15 +192,21 @@
   pseudo::pairBrackets(ParseableStream);
 
   std::vector Result;
-  auto ToFoldingRange = [](Position Start, Position End,
-   llvm::StringLiteral Kind) {
+  auto AddFoldingRange = [&](Position Start, Position End,
+ llvm::StringLiteral Kind) {
+if (Start.line >= End.line)
+  return;
 FoldingRange FR;
 FR.startLine = Start.line;
-FR.startCharacter = Start.character;
 FR.endLine = End.line;
-FR.endCharacter = End.character;
+if (LineFoldingsOnly)
+  FR.startCharacter = FR.endCharacter = 0;
+else {
+  FR.startCharacter = Start.character;
+  FR.endCharacter = End.character;
+}
 FR.kind = Kind.str();
-return FR;
+Result.push_back(FR);
   };
   auto OriginalToken = [&](const pseudo::Token &T) {
 return OrigSt

[PATCH] D131479: Handle explicitly defaulted consteval special members.

2022-08-09 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131479

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -766,3 +766,55 @@
   static_assert(c == 8);
 }
 }
+
+namespace DefaultedTemp {
+template 
+struct default_ctor {
+  T data;
+  consteval default_ctor() = default; // expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+};
+
+template 
+struct copy {
+  T data;
+
+  consteval copy(const copy &) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval copy &operator=(const copy &) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  copy() = default;
+};
+
+template 
+struct move {
+  T data;
+
+  consteval move(move &&) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval move &operator=(move &&) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  move() = default;
+};
+
+struct foo {
+  foo() {}// expected-note {{declared here}}
+  foo(const foo &) {} // expected-note {{declared here}}
+  foo(foo &&) {}  // expected-note {{declared here}}
+
+  foo& operator=(const foo &) { return *this; } // expected-note {{declared here}}
+  foo& operator=(foo &&) { return *this; }  // expected-note {{declared here}}
+};
+
+void func() {
+  default_ctor fail0; // expected-error {{call to consteval function 'DefaultedTemp::default_ctor::default_ctor' is not a constant expression}} \
+  expected-note {{in call to 'default_ctor()'}}
+
+  copy good0;
+  copy fail1{good0}; // expected-error {{call to consteval function 'DefaultedTemp::copy::copy' is not a constant expression}} \
+ expected-note {{in call to 'copy(good0)'}}
+  fail1 = good0;  // expected-error {{call to consteval function 'DefaultedTemp::copy::operator=' is not a constant expression}} \
+ expected-note {{in call to '&fail1->operator=(good0)'}}
+
+  move good1;
+  move fail2{static_cast&&>(good1)}; // expected-error {{call to consteval function 'DefaultedTemp::move::move' is not a constant expression}} \
+   expected-note {{in call to 'move(good1)'}}
+  fail2 = static_cast&&>(good1);  // expected-error {{call to consteval function 'DefaultedTemp::move::operator=' is not a constant expression}} \
+   expected-note {{in call to '&fail2->operator=(good1)'}}
+}
+} // namespace DefaultedTemp
Index: clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
===
--- clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -44,18 +44,20 @@
 }
 
 template struct S : T {
-  constexpr S() = default;
-  constexpr S(const S&) = default;
-  constexpr S(S&&) = default;
+  constexpr S() = default; // expected-note {{previous declaration is here}}
+  constexpr S(const S&) = default; // expected-note {{previous declaration is here}}
+  constexpr S(S&&) = default;  // expected-note {{previous declaration is here}}
 };
 struct lit { constexpr lit() {} };
 S s_lit; // ok
 S s_bar; // ok
 
 struct Friends {
-  friend S::S();
-  friend S::S(const S&);
-  friend S::S(S&&);
+  // FIXME: these error may or may not be correct; there is an open question on
+  // the CWG reflectors about this.
+  friend S::S();  // expected-error {{non-constexpr declaration of 'S' follows constexpr declaration}}
+  friend S::S(const S&);  // expected-error {{non-constexpr declaration of 'S' follows constexpr declaration}}
+  friend S::S(S&&);   // expected-error {{non-constexpr declaration of 'S' follows constexpr declaration}}
 };
 
 namespace DefaultedFnExceptionSpec {
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/ComparisonCategories.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecordLayout.h"
@@ -7202,10 +7203,24 @@
 static bool defaultedSpecialMemberIsConstexpr

[PATCH] D131479: Handle explicitly defaulted consteval special members.

2022-08-09 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 451333.
usaxena95 added a comment.

Added tests for multiple constructors in a templated class.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131479

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -766,3 +766,89 @@
   static_assert(c == 8);
 }
 }
+
+namespace defaulted_special_member_template {
+template 
+struct default_ctor {
+  T data;
+  consteval default_ctor() = default; // expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+};
+
+template 
+struct copy {
+  T data;
+
+  consteval copy(const copy &) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval copy &operator=(const copy &) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  copy() = default;
+};
+
+template 
+struct move {
+  T data;
+
+  consteval move(move &&) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval move &operator=(move &&) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  move() = default;
+};
+
+struct foo {
+  foo() {}// expected-note {{declared here}}
+  foo(const foo &) {} // expected-note {{declared here}}
+  foo(foo &&) {}  // expected-note {{declared here}}
+
+  foo& operator=(const foo &) { return *this; } // expected-note {{declared here}}
+  foo& operator=(foo &&) { return *this; }  // expected-note {{declared here}}
+};
+
+void func() {
+  default_ctor fail0; // expected-error-re {{call to consteval function '{{.*::default_ctor<.*::foo>}}::default_ctor' is not a constant expression}} \
+  expected-note {{in call to 'default_ctor()'}}
+
+  copy good0;
+  copy fail1{good0}; // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::copy' is not a constant expression}} \
+ expected-note {{in call to 'copy(good0)'}}
+  fail1 = good0;  // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::operator=' is not a constant expression}} \
+ expected-note {{in call to '&fail1->operator=(good0)'}}
+
+  move good1;
+  move fail2{static_cast&&>(good1)}; // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::move' is not a constant expression}} \
+   expected-note {{in call to 'move(good1)'}}
+  fail2 = static_cast&&>(good1);  // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::operator=' is not a constant expression}} \
+   expected-note {{in call to '&fail2->operator=(good1)'}}
+}
+} // namespace defaulted_special_member_template
+
+namespace multiple_default_constructors {
+struct Foo {
+  Foo() {}; // expected-note {{declared here}}
+};
+struct Bar {
+  Bar() = default;
+};
+struct Baz {
+  consteval Baz() {}
+};
+
+template 
+struct S {
+  T data;
+  S() requires (N==1) = default;
+  S() requires (N==2) {}
+  consteval S() requires (N==3) = default;  // expected-note {{non-constexpr constructor 'Foo' cannot be used in a constant expression}}
+};
+
+void func() {
+  // Explictly defaulted constructor.
+  S s1;
+  S s2;
+  // User provided constructor.
+  S s3;
+  S s4;
+  // Consteval explictly defaulted constructor.
+  S s5; // expected-error-re {{call to consteval function '{{.*}}::S<{{.*}}::Foo, 3>::S' is not a constant expression}} \
+   expected-note {{in call to 'S()'}}
+  S s6;
+  S s7;
+}
+} // namespace multiple_default_constructors
Index: clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
===
--- clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -44,18 +44,20 @@
 }
 
 template struct S : T {
-  constexpr S() = default;
-  constexpr S(const S&) = default;
-  constexpr S(S&&) = default;
+  constexpr S() = default; // expected-note {{previous declaration is here}}
+  constexpr S(const S&) = default; // expected-note {{previous declaration is here}}
+  constexpr S(S&&) = default;  // expected-note {{previous declaration is here}}
 };
 struct lit { constexpr lit() {} };
 S s_lit; // ok
 S s_bar; // ok
 
 struct Friends {
-  friend S::S();
-  friend S::S(const S&);
-  friend S::S(S&&);
+  // FIXME: these error may or may not be correct; there is an open question on
+  // the CWG

[PATCH] D131479: Handle explicitly defaulted consteval special members.

2022-08-09 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 451353.
usaxena95 added a comment.

Verify that non-consteval constructors (among others) cannot be used in a 
consteval context.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131479

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -766,3 +766,102 @@
   static_assert(c == 8);
 }
 }
+
+namespace defaulted_special_member_template {
+template 
+struct default_ctor {
+  T data;
+  consteval default_ctor() = default; // expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+};
+
+template 
+struct copy {
+  T data;
+
+  consteval copy(const copy &) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval copy &operator=(const copy &) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  copy() = default;
+};
+
+template 
+struct move {
+  T data;
+
+  consteval move(move &&) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval move &operator=(move &&) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  move() = default;
+};
+
+struct foo {
+  foo() {}// expected-note {{declared here}}
+  foo(const foo &) {} // expected-note {{declared here}}
+  foo(foo &&) {}  // expected-note {{declared here}}
+
+  foo& operator=(const foo &) { return *this; } // expected-note {{declared here}}
+  foo& operator=(foo &&) { return *this; }  // expected-note {{declared here}}
+};
+
+void func() {
+  default_ctor fail0; // expected-error-re {{call to consteval function '{{.*::default_ctor<.*::foo>}}::default_ctor' is not a constant expression}} \
+  expected-note {{in call to 'default_ctor()'}}
+
+  copy good0;
+  copy fail1{good0}; // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::copy' is not a constant expression}} \
+ expected-note {{in call to 'copy(good0)'}}
+  fail1 = good0;  // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::operator=' is not a constant expression}} \
+ expected-note {{in call to '&fail1->operator=(good0)'}}
+
+  move good1;
+  move fail2{static_cast&&>(good1)}; // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::move' is not a constant expression}} \
+   expected-note {{in call to 'move(good1)'}}
+  fail2 = static_cast&&>(good1);  // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::operator=' is not a constant expression}} \
+   expected-note {{in call to '&fail2->operator=(good1)'}}
+}
+} // namespace defaulted_special_member_template
+
+namespace multiple_default_constructors {
+struct Foo {
+  Foo() {} // expected-note {{declared here}}
+};
+struct Bar {
+  Bar() = default;
+};
+struct Baz {
+  consteval Baz() {}
+};
+
+template 
+struct S {
+  T data;
+  S() requires (N==1) = default;
+  // This cannot be used in constexpr context.
+  S() requires (N==2) {}  // expected-note {{declared here}}
+  consteval S() requires (N==3) = default;  // expected-note {{non-constexpr constructor 'Foo' cannot be used in a constant expression}}
+};
+
+void func() {
+  // Explictly defaulted constructor.
+  S s1;
+  S s2;
+  // User provided constructor.
+  S s3;
+  S s4;
+  // Consteval explictly defaulted constructor.
+  S s5; // expected-error-re {{call to consteval function '{{.*}}::S<{{.*}}::Foo, 3>::S' is not a constant expression}} \
+   expected-note {{in call to 'S()'}}
+  S s6;
+  S s7;
+}
+
+consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}}
+  // Defaulted default constructors are consteval.
+  S s1;
+
+  S s4; // expected-note {{non-constexpr constructor 'S' cannot be used in a constant expression}}
+
+  S s2;
+  S s3;
+  return 0;
+}
+
+} // namespace multiple_default_constructors
Index: clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
===
--- clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -44,18 +44,20 @@
 }
 
 template struct S : T {
-  constexpr S() = default;
-  constexpr S(const S&) = default;
-  constexpr S(S&&) = default;
+  constexpr S() = default; // expected-note {{previous declarat

[PATCH] D131479: Handle explicitly defaulted consteval special members.

2022-08-10 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 451432.
usaxena95 marked an inline comment as done.
usaxena95 added a comment.

Addressed comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131479

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -766,3 +766,102 @@
   static_assert(c == 8);
 }
 }
+
+namespace defaulted_special_member_template {
+template 
+struct default_ctor {
+  T data;
+  consteval default_ctor() = default; // expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+};
+
+template 
+struct copy {
+  T data;
+
+  consteval copy(const copy &) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval copy &operator=(const copy &) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  copy() = default;
+};
+
+template 
+struct move {
+  T data;
+
+  consteval move(move &&) = default;// expected-note {{non-constexpr constructor 'foo' cannot be used in a constant expression}}
+  consteval move &operator=(move &&) = default; // expected-note {{non-constexpr function 'operator=' cannot be used in a constant expression}}
+  move() = default;
+};
+
+struct foo {
+  foo() {}// expected-note {{declared here}}
+  foo(const foo &) {} // expected-note {{declared here}}
+  foo(foo &&) {}  // expected-note {{declared here}}
+
+  foo& operator=(const foo &) { return *this; } // expected-note {{declared here}}
+  foo& operator=(foo &&) { return *this; }  // expected-note {{declared here}}
+};
+
+void func() {
+  default_ctor fail0; // expected-error-re {{call to consteval function '{{.*::default_ctor<.*::foo>}}::default_ctor' is not a constant expression}} \
+  expected-note {{in call to 'default_ctor()'}}
+
+  copy good0;
+  copy fail1{good0}; // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::copy' is not a constant expression}} \
+ expected-note {{in call to 'copy(good0)'}}
+  fail1 = good0;  // expected-error-re {{call to consteval function '{{.*::copy<.*::foo>}}::operator=' is not a constant expression}} \
+ expected-note {{in call to '&fail1->operator=(good0)'}}
+
+  move good1;
+  move fail2{static_cast&&>(good1)}; // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::move' is not a constant expression}} \
+   expected-note {{in call to 'move(good1)'}}
+  fail2 = static_cast&&>(good1);  // expected-error-re {{call to consteval function '{{.*::move<.*::foo>}}::operator=' is not a constant expression}} \
+   expected-note {{in call to '&fail2->operator=(good1)'}}
+}
+} // namespace defaulted_special_member_template
+
+namespace multiple_default_constructors {
+struct Foo {
+  Foo() {} // expected-note {{declared here}}
+};
+struct Bar {
+  Bar() = default;
+};
+struct Baz {
+  consteval Baz() {}
+};
+
+template 
+struct S {
+  T data;
+  S() requires (N==1) = default;
+  // This cannot be used in constexpr context.
+  S() requires (N==2) {}  // expected-note {{declared here}}
+  consteval S() requires (N==3) = default;  // expected-note {{non-constexpr constructor 'Foo' cannot be used in a constant expression}}
+};
+
+void func() {
+  // Explictly defaulted constructor.
+  S s1;
+  S s2;
+  // User provided constructor.
+  S s3;
+  S s4;
+  // Consteval explictly defaulted constructor.
+  S s5; // expected-error-re {{call to consteval function '{{.*}}::S<{{.*}}::Foo, 3>::S' is not a constant expression}} \
+   expected-note {{in call to 'S()'}}
+  S s6;
+  S s7;
+}
+
+consteval int aConstevalFunction() { // expected-error {{consteval function never produces a constant expression}}
+  // Defaulted default constructors are consteval.
+  S s1;
+
+  S s4; // expected-note {{non-constexpr constructor 'S' cannot be used in a constant expression}}
+
+  S s2;
+  S s3;
+  return 0;
+}
+
+} // namespace multiple_default_constructors
Index: clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
===
--- clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
+++ clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
@@ -44,18 +44,20 @@
 }
 
 template struct S : T {
-  constexpr S() = default;
-  constexpr S(const S&) = default;
-  constexpr S(S&&) = default;
+  constexpr S() = default; // expected-note {{previous declaration is here}}
+  constexpr S(co

[PATCH] D131479: Handle explicitly defaulted consteval special members.

2022-08-10 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 added a comment.

As discussed offline, we are already following the discussion 2602 
.
We are keeping the constructor `consteval` to allow complaining when we are 
actually processing the call to data member constructors (instead of the 
`consteval` constructor itself.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D131479

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


[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-13 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 created this revision.
Herald added subscribers: kadircet, arphaman, mgorny.
Herald added a project: All.
usaxena95 requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

For sharing. WIP


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129648

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/pseudo/include/clang-pseudo/Token.h
  clang-tools-extra/pseudo/lib/Lex.cpp

Index: clang-tools-extra/pseudo/lib/Lex.cpp
===
--- clang-tools-extra/pseudo/lib/Lex.cpp
+++ clang-tools-extra/pseudo/lib/Lex.cpp
@@ -27,6 +27,7 @@
   TokenStream Result;
   clang::Token CT;
   unsigned LastOffset = 0;
+  unsigned LineStartOffset = 0;
   unsigned Line = 0;
   unsigned Indent = 0;
   for (Lexer.LexFromRawLexer(CT); CT.getKind() != clang::tok::eof;
@@ -40,16 +41,17 @@
 Tok.Kind = CT.getKind();
 
 // Update current line number and indentation from raw source code.
-unsigned NewLineStart = 0;
+bool SawNewLine = 0;
 for (unsigned I = LastOffset; I < Offset; ++I) {
   if (Code[I] == '\n') {
-NewLineStart = I + 1;
+LineStartOffset = I + 1;
+SawNewLine = true;
 ++Line;
   }
 }
-if (NewLineStart || !LastOffset) {
+if (SawNewLine || !LastOffset) {
   Indent = 0;
-  for (char C : StringRef(Code).slice(NewLineStart, Offset)) {
+  for (char C : StringRef(Code).slice(LineStartOffset, Offset)) {
 if (C == ' ')
   ++Indent;
 else if (C == '\t')
@@ -60,6 +62,7 @@
 }
 Tok.Indent = Indent;
 Tok.Line = Line;
+Tok.StartColumn = Offset - LineStartOffset;
 
 if (CT.isAtStartOfLine())
   Tok.setFlag(LexFlags::StartsPPLine);
Index: clang-tools-extra/pseudo/include/clang-pseudo/Token.h
===
--- clang-tools-extra/pseudo/include/clang-pseudo/Token.h
+++ clang-tools-extra/pseudo/include/clang-pseudo/Token.h
@@ -63,6 +63,9 @@
   /// Zero-based line number for the start of the token.
   /// This refers to the original source file as written.
   uint32_t Line = 0;
+  /// Zero-based column number for the start of the token.
+  /// This refers to the original source file as written.
+  uint8_t StartColumn = 0;
   /// Width of whitespace before the first token on this line.
   uint8_t Indent = 0;
   /// Flags have some meaning defined by the function that produced this stream.
@@ -96,7 +99,7 @@
   /// If this token is a paired bracket, the offset of the pair in the stream.
   int32_t Pair = 0;
 };
-static_assert(sizeof(Token) <= sizeof(char *) + 20, "Careful with layout!");
+static_assert(sizeof(Token) <= sizeof(char *) + 24, "Careful with layout!");
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Token &);
 
 /// A half-open range of tokens within a stream.
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -240,7 +240,7 @@
 ]]}
   )cpp",
   R"cpp(
-class Foo {
+class Foo {[[
 public:
   Foo() {[[
 int X = 1;
@@ -253,14 +253,15 @@
 
   // Braces are located at the same line: no folding range here.
   void getFooBar() { }
-};
+]]};
   )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
 auto AST = TestTU::withCode(T.code()).build();
-EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(
+gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -15,6 +15,7 @@
 #include "ParsedAST.h"
 #include "Protocol.h"
 #include "llvm/Support/Error.h"
+#include 
 #include 
 namespace clang {
 namespace clangd {
@@ -29,6 +30,10 @@
 /// This should include large scopes, preprocessor blocks etc.
 llvm::Expected> getFoldingRanges(ParsedAST &AST);
 
+/// FILL ME.
+llvm::Expected>
+getFoldingRanges(const std::string &Code);
+
 } // namespace clangd
 } // namespace clang
 
Index: clang-tools-extra/clangd/SemanticSelection.cpp
===
--- clang-tools-extra/clangd/SemanticSelection.cpp
+++ clang-tools-extra/clangd/SemanticSelection.cpp
@@ -11,15 

[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-14 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 444755.
usaxena95 added a comment.

Addressed offline comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129648

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/pseudo/include/clang-pseudo/Token.h
  clang-tools-extra/pseudo/lib/Lex.cpp

Index: clang-tools-extra/pseudo/lib/Lex.cpp
===
--- clang-tools-extra/pseudo/lib/Lex.cpp
+++ clang-tools-extra/pseudo/lib/Lex.cpp
@@ -26,7 +26,10 @@
 
   TokenStream Result;
   clang::Token CT;
+  // Index into the token stream of original source code.
+  unsigned TokenIdx = 0;
   unsigned LastOffset = 0;
+  unsigned LineStartOffset = 0;
   unsigned Line = 0;
   unsigned Indent = 0;
   for (Lexer.LexFromRawLexer(CT); CT.getKind() != clang::tok::eof;
@@ -40,16 +43,17 @@
 Tok.Kind = CT.getKind();
 
 // Update current line number and indentation from raw source code.
-unsigned NewLineStart = 0;
+bool SawNewLine = 0;
 for (unsigned I = LastOffset; I < Offset; ++I) {
   if (Code[I] == '\n') {
-NewLineStart = I + 1;
+LineStartOffset = I + 1;
+SawNewLine = true;
 ++Line;
   }
 }
-if (NewLineStart || !LastOffset) {
+if (SawNewLine || !LastOffset) {
   Indent = 0;
-  for (char C : StringRef(Code).slice(NewLineStart, Offset)) {
+  for (char C : StringRef(Code).slice(LineStartOffset, Offset)) {
 if (C == ' ')
   ++Indent;
 else if (C == '\t')
@@ -66,9 +70,12 @@
 if (CT.needsCleaning() || CT.hasUCN())
   Tok.setFlag(LexFlags::NeedsCleaning);
 
+Tok.OrigTokIdx = TokenIdx;
 Result.push(Tok);
 LastOffset = Offset;
+TokenIdx++;
   }
+  Result.setOriginal();
   Result.finalize();
   return Result;
 }
Index: clang-tools-extra/pseudo/include/clang-pseudo/Token.h
===
--- clang-tools-extra/pseudo/include/clang-pseudo/Token.h
+++ clang-tools-extra/pseudo/include/clang-pseudo/Token.h
@@ -33,6 +33,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/raw_ostream.h"
+#include 
 #include 
 #include 
 #include 
@@ -67,6 +68,8 @@
   uint8_t Indent = 0;
   /// Flags have some meaning defined by the function that produced this stream.
   uint8_t Flags = 0;
+  /// Index into the original token stream (of the original source file).
+  Index OrigTokIdx = 0;
   // Helpers to get/set Flags based on `enum class`.
   template  bool flag(T Mask) const {
 return Flags & uint8_t{static_cast>(Mask)};
@@ -96,7 +99,7 @@
   /// If this token is a paired bracket, the offset of the pair in the stream.
   int32_t Pair = 0;
 };
-static_assert(sizeof(Token) <= sizeof(char *) + 20, "Careful with layout!");
+static_assert(sizeof(Token) <= sizeof(char *) + 24, "Careful with layout!");
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Token &);
 
 /// A half-open range of tokens within a stream.
@@ -170,6 +173,18 @@
 return Storage[1];
   }
 
+  /// An original token stream corresponds to the original source file (Eg.
+  /// produced by lex()). It is not derived from another token stream.
+  bool isOriginal() const { return IsOriginal; }
+  void setOriginal() { IsOriginal = true; }
+
+  /// Extracts the token in original stream corresponding to Token T.
+  const Token &origToken(const Token &T) const {
+assert(isOriginal() && "stream is derived");
+assert(T.OrigTokIdx < tokens().size() && "invalid index");
+return tokens()[T.OrigTokIdx];
+  }
+
   /// Print the tokens in this stream to the output stream.
   ///
   /// The presence of newlines/spaces is preserved, but not the quantity.
@@ -180,6 +195,7 @@
 
   MutableArrayRef Tokens;
   std::vector Storage; // eof + Tokens + eof
+  bool IsOriginal = false;
 };
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TokenStream &);
 
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -240,7 +240,7 @@
 ]]}
   )cpp",
   R"cpp(
-class Foo {
+class Foo {[[
 public:
   Foo() {[[
 int X = 1;
@@ -253,14 +253,25 @@
 
   // Braces are located at the same line: no folding range here.
   void getFooBar() { }
-};
+]]};
+  )cpp",
+  R"cpp(
+// Range boundaries on escaped newlines.
+class Foo \
+\
+{[[  \
+public:
+  Foo() {[[\
+int X = 1;
+  ]]}   \
+]]};
   )cp

[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-14 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 444765.
usaxena95 added a comment.

Removed changes from previous revision.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129648

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/pseudo/include/clang-pseudo/Token.h
  clang-tools-extra/pseudo/lib/Lex.cpp

Index: clang-tools-extra/pseudo/lib/Lex.cpp
===
--- clang-tools-extra/pseudo/lib/Lex.cpp
+++ clang-tools-extra/pseudo/lib/Lex.cpp
@@ -26,6 +26,8 @@
 
   TokenStream Result;
   clang::Token CT;
+  // Index into the token stream of original source code.
+  unsigned TokenIdx = 0;
   unsigned LastOffset = 0;
   unsigned Line = 0;
   unsigned Indent = 0;
@@ -66,9 +68,12 @@
 if (CT.needsCleaning() || CT.hasUCN())
   Tok.setFlag(LexFlags::NeedsCleaning);
 
+Tok.OrigTokIdx = TokenIdx++;
 Result.push(Tok);
 LastOffset = Offset;
   }
+  // This stream represents the original source code.
+  Result.setOriginal();
   Result.finalize();
   return Result;
 }
Index: clang-tools-extra/pseudo/include/clang-pseudo/Token.h
===
--- clang-tools-extra/pseudo/include/clang-pseudo/Token.h
+++ clang-tools-extra/pseudo/include/clang-pseudo/Token.h
@@ -33,6 +33,7 @@
 #include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/raw_ostream.h"
+#include 
 #include 
 #include 
 #include 
@@ -67,6 +68,8 @@
   uint8_t Indent = 0;
   /// Flags have some meaning defined by the function that produced this stream.
   uint8_t Flags = 0;
+  /// Index into the original token stream (of the original source file).
+  Index OrigTokIdx = 0;
   // Helpers to get/set Flags based on `enum class`.
   template  bool flag(T Mask) const {
 return Flags & uint8_t{static_cast>(Mask)};
@@ -96,7 +99,7 @@
   /// If this token is a paired bracket, the offset of the pair in the stream.
   int32_t Pair = 0;
 };
-static_assert(sizeof(Token) <= sizeof(char *) + 20, "Careful with layout!");
+static_assert(sizeof(Token) <= sizeof(char *) + 24, "Careful with layout!");
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Token &);
 
 /// A half-open range of tokens within a stream.
@@ -170,6 +173,18 @@
 return Storage[1];
   }
 
+  /// An original token stream corresponds to the original source file (Eg.
+  /// produced by lex()). It is not derived from another token stream.
+  bool isOriginal() const { return IsOriginal; }
+  void setOriginal() { IsOriginal = true; }
+
+  /// Extracts the token in original stream corresponding to Token T.
+  const Token &origToken(const Token &T) const {
+assert(isOriginal() && "stream is derived");
+assert(T.OrigTokIdx < tokens().size() && "invalid index");
+return tokens()[T.OrigTokIdx];
+  }
+
   /// Print the tokens in this stream to the output stream.
   ///
   /// The presence of newlines/spaces is preserved, but not the quantity.
@@ -180,6 +195,7 @@
 
   MutableArrayRef Tokens;
   std::vector Storage; // eof + Tokens + eof
+  bool IsOriginal = false;
 };
 llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TokenStream &);
 
Index: clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
@@ -240,7 +240,7 @@
 ]]}
   )cpp",
   R"cpp(
-class Foo {
+class Foo {[[
 public:
   Foo() {[[
 int X = 1;
@@ -253,14 +253,25 @@
 
   // Braces are located at the same line: no folding range here.
   void getFooBar() { }
-};
+]]};
+  )cpp",
+  R"cpp(
+// Range boundaries on escaped newlines.
+class Foo \
+\
+{[[  \
+public:
+  Foo() {[[\
+int X = 1;
+  ]]}   \
+]]};
   )cpp",
   };
   for (const char *Test : Tests) {
 auto T = Annotations(Test);
-auto AST = TestTU::withCode(T.code()).build();
-EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
-UnorderedElementsAreArray(T.ranges()))
+EXPECT_THAT(
+gatherFoldingRanges(llvm::cantFail(getFoldingRanges(T.code().str(,
+UnorderedElementsAreArray(T.ranges()))
 << Test;
   }
 }
Index: clang-tools-extra/clangd/SemanticSelection.h
===
--- clang-tools-extra/clangd/SemanticSelection.h
+++ clang-tools-extra/clangd/SemanticSelection.h
@@ -15,6 +15,7 @@
 #include "ParsedAST.h"
 #include "Protocol.h"
 #include "llvm/Support/Error.h"

[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-15 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 444975.
usaxena95 marked 15 inline comments as done.
usaxena95 added a comment.

Addressed comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129648

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/pseudo/include/clang-pseudo/Token.h
  clang-tools-extra/pseudo/lib/CMakeLists.txt
  clang-tools-extra/pseudo/lib/Lex.cpp
  clang-tools-extra/pseudo/unittests/TokenTest.cpp

Index: clang-tools-extra/pseudo/unittests/TokenTest.cpp
===
--- clang-tools-extra/pseudo/unittests/TokenTest.cpp
+++ clang-tools-extra/pseudo/unittests/TokenTest.cpp
@@ -31,6 +31,10 @@
   return arg.Line == (unsigned)Line && arg.Indent == (unsigned)Indent;
 }
 
+MATCHER_P(originalIndex, index, "") {
+  return arg.OriginalIndex == (Token::Index)index;
+}
+
 TEST(TokenTest, Lex) {
   LangOptions Opts;
   std::string Code = R"cpp(
@@ -105,20 +109,23 @@
   Raw.tokens(),
   ElementsAre(AllOf(token("one_\\\ntoken", tok::raw_identifier),
 hasFlag(LexFlags::StartsPPLine),
-hasFlag(LexFlags::NeedsCleaning), lineIndent(1, 0)),
+hasFlag(LexFlags::NeedsCleaning), lineIndent(1, 0),
+originalIndex(0)),
   AllOf(token("two", tok::raw_identifier),
 hasFlag(LexFlags::StartsPPLine),
-Not(hasFlag(LexFlags::NeedsCleaning))),
+Not(hasFlag(LexFlags::NeedsCleaning)),
+originalIndex(1)),
   AllOf(token("\\\ntokens", tok::raw_identifier),
 Not(hasFlag(LexFlags::StartsPPLine)),
-hasFlag(LexFlags::NeedsCleaning;
+hasFlag(LexFlags::NeedsCleaning), originalIndex(2;
 
   TokenStream Cooked = cook(Raw, Opts);
   EXPECT_THAT(
   Cooked.tokens(),
-  ElementsAre(AllOf(token("one_token", tok::identifier), lineIndent(1, 0)),
-  token("two", tok::identifier),
-  token("tokens", tok::identifier)));
+  ElementsAre(AllOf(token("one_token", tok::identifier), lineIndent(1, 0),
+originalIndex(0)),
+  AllOf(token("two", tok::identifier), originalIndex(1)),
+  AllOf(token("tokens", tok::identifier), originalIndex(2;
 }
 
 TEST(TokenTest, EncodedCharacters) {
@@ -182,13 +189,14 @@
 )cpp";
   TokenStream Cook = cook(lex(Code, Opts), Opts);
   TokenStream Split = stripComments(Cook);
-  EXPECT_THAT(Split.tokens(), ElementsAreArray({
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">>=", tok::greatergreaterequal),
-  }));
+  EXPECT_THAT(Split.tokens(),
+  ElementsAre(AllOf(token(">", tok::greater), originalIndex(0)),
+  AllOf(token(">", tok::greater), originalIndex(0)),
+  // Token and 1 and 2 are comments.
+  AllOf(token(">", tok::greater), originalIndex(3)),
+  AllOf(token(">", tok::greater), originalIndex(3)),
+  AllOf(token(">>=", tok::greatergreaterequal),
+originalIndex(4;
 }
 
 TEST(TokenTest, DropComments) {
@@ -199,13 +207,16 @@
 )cpp";
   TokenStream Raw = cook(lex(Code, Opts), Opts);
   TokenStream Stripped = stripComments(Raw);
-  EXPECT_THAT(Raw.tokens(),
-  ElementsAreArray(
-  {token("// comment", tok::comment), token("int", tok::kw_int),
-   token("/*abc*/", tok::comment), token(";", tok::semi)}));
-
-  EXPECT_THAT(Stripped.tokens(), ElementsAreArray({token("int", tok::kw_int),
-   token(";", tok::semi)}));
+  EXPECT_THAT(
+  Raw.tokens(),
+  ElementsAre(AllOf(token("// comment", tok::comment), originalIndex(0)),
+  AllOf(token("int", tok::kw_int), originalIndex(1)),
+  AllOf(token("/*abc*/", tok::comment), originalIndex(2)),
+  AllOf(token(";", tok::semi), originalIndex(3;
+
+  EXPECT_THAT(Stripped.tokens(),
+  ElementsAre(AllOf(token("int", tok::kw_int), originalIndex(1)),
+  AllOf(token(";", tok::semi), originalIndex(3;
 }
 
 } // namespace
Index: clang-tools-extra/pseudo/lib/Lex.cpp
===
--- clang-tools-extra/pseudo/l

[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-15 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 added inline comments.



Comment at: clang-tools-extra/clangd/SemanticSelection.cpp:185
+if (auto *Paired = Tok.pair()) {
+  if (Tok.Line < Paired->Line) {
+Position Start = offsetToPosition(

hokein wrote:
> The `if` logic seems tricky, it is doing two different things:
> 
> 1) avoid creating duplicate `FoldingRange` for a pair bracket
> 2) avoid creating a FoldingRange if the pair bracket is on the same line.
> 
> Are both intended?
Yes. Both of these are intentional. Added a comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129648

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


[PATCH] D129648: Use pseudo parser for folding ranges

2022-07-15 Thread Utkarsh Saxena via Phabricator via cfe-commits
usaxena95 updated this revision to Diff 445002.
usaxena95 added a comment.

Removed unused headers and fix spellings.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D129648

Files:
  clang-tools-extra/clangd/CMakeLists.txt
  clang-tools-extra/clangd/SemanticSelection.cpp
  clang-tools-extra/clangd/SemanticSelection.h
  clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
  clang-tools-extra/pseudo/include/clang-pseudo/Token.h
  clang-tools-extra/pseudo/lib/CMakeLists.txt
  clang-tools-extra/pseudo/lib/Lex.cpp
  clang-tools-extra/pseudo/unittests/TokenTest.cpp

Index: clang-tools-extra/pseudo/unittests/TokenTest.cpp
===
--- clang-tools-extra/pseudo/unittests/TokenTest.cpp
+++ clang-tools-extra/pseudo/unittests/TokenTest.cpp
@@ -31,6 +31,10 @@
   return arg.Line == (unsigned)Line && arg.Indent == (unsigned)Indent;
 }
 
+MATCHER_P(originalIndex, index, "") {
+  return arg.OriginalIndex == (Token::Index)index;
+}
+
 TEST(TokenTest, Lex) {
   LangOptions Opts;
   std::string Code = R"cpp(
@@ -105,20 +109,23 @@
   Raw.tokens(),
   ElementsAre(AllOf(token("one_\\\ntoken", tok::raw_identifier),
 hasFlag(LexFlags::StartsPPLine),
-hasFlag(LexFlags::NeedsCleaning), lineIndent(1, 0)),
+hasFlag(LexFlags::NeedsCleaning), lineIndent(1, 0),
+originalIndex(0)),
   AllOf(token("two", tok::raw_identifier),
 hasFlag(LexFlags::StartsPPLine),
-Not(hasFlag(LexFlags::NeedsCleaning))),
+Not(hasFlag(LexFlags::NeedsCleaning)),
+originalIndex(1)),
   AllOf(token("\\\ntokens", tok::raw_identifier),
 Not(hasFlag(LexFlags::StartsPPLine)),
-hasFlag(LexFlags::NeedsCleaning;
+hasFlag(LexFlags::NeedsCleaning), originalIndex(2;
 
   TokenStream Cooked = cook(Raw, Opts);
   EXPECT_THAT(
   Cooked.tokens(),
-  ElementsAre(AllOf(token("one_token", tok::identifier), lineIndent(1, 0)),
-  token("two", tok::identifier),
-  token("tokens", tok::identifier)));
+  ElementsAre(AllOf(token("one_token", tok::identifier), lineIndent(1, 0),
+originalIndex(0)),
+  AllOf(token("two", tok::identifier), originalIndex(1)),
+  AllOf(token("tokens", tok::identifier), originalIndex(2;
 }
 
 TEST(TokenTest, EncodedCharacters) {
@@ -182,13 +189,14 @@
 )cpp";
   TokenStream Cook = cook(lex(Code, Opts), Opts);
   TokenStream Split = stripComments(Cook);
-  EXPECT_THAT(Split.tokens(), ElementsAreArray({
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">", tok::greater),
-  token(">>=", tok::greatergreaterequal),
-  }));
+  EXPECT_THAT(Split.tokens(),
+  ElementsAre(AllOf(token(">", tok::greater), originalIndex(0)),
+  AllOf(token(">", tok::greater), originalIndex(0)),
+  // Token 1 and 2 are comments.
+  AllOf(token(">", tok::greater), originalIndex(3)),
+  AllOf(token(">", tok::greater), originalIndex(3)),
+  AllOf(token(">>=", tok::greatergreaterequal),
+originalIndex(4;
 }
 
 TEST(TokenTest, DropComments) {
@@ -199,13 +207,16 @@
 )cpp";
   TokenStream Raw = cook(lex(Code, Opts), Opts);
   TokenStream Stripped = stripComments(Raw);
-  EXPECT_THAT(Raw.tokens(),
-  ElementsAreArray(
-  {token("// comment", tok::comment), token("int", tok::kw_int),
-   token("/*abc*/", tok::comment), token(";", tok::semi)}));
-
-  EXPECT_THAT(Stripped.tokens(), ElementsAreArray({token("int", tok::kw_int),
-   token(";", tok::semi)}));
+  EXPECT_THAT(
+  Raw.tokens(),
+  ElementsAre(AllOf(token("// comment", tok::comment), originalIndex(0)),
+  AllOf(token("int", tok::kw_int), originalIndex(1)),
+  AllOf(token("/*abc*/", tok::comment), originalIndex(2)),
+  AllOf(token(";", tok::semi), originalIndex(3;
+
+  EXPECT_THAT(Stripped.tokens(),
+  ElementsAre(AllOf(token("int", tok::kw_int), originalIndex(1)),
+  AllOf(token(";", tok::semi), originalIndex(3;
 }
 
 } // namespace
Index: clang-tools-extra/pseudo/lib/Lex.cpp
===
--- clang-tools-extra/pseudo/lib/Lex.cpp
+++ clang-tools-

  1   2   3   4   5   >