[PATCH] D63128: Fixed google-readability-casting test to work in c++17

2019-06-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: gribozavr, hokein.
Herald added a project: clang.

Fixed google-readability-casting.cpp to get tests working in c++17


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63128

Files:
  clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
  clang-tools-extra/test/clang-tidy/google-readability-casting.cpp


Index: clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
===
--- clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
+++ clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s google-readability-casting %t
+// RUN: %check_clang_tidy -std=c++11-or-later %s google-readability-casting %t
 // FIXME: Fix the checker to work in C++17 mode.
 
 bool g() { return false; }
Index: clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
===
--- clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -86,6 +86,10 @@
   bool FnToFnCast =
   isFunction(SourceTypeAsWritten) && isFunction(DestTypeAsWritten);
 
+  const bool ConstructorCast = !CastExpr->getTypeAsWritten().hasQualifiers() &&
+  DestTypeAsWritten->isRecordType() &&
+  !DestTypeAsWritten->isElaboratedTypeSpecifier();
+
   if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) {
 // Function pointer/reference casts may be needed to resolve ambiguities in
 // case of overloaded functions, so detection of redundant casts is 
trickier
@@ -144,19 +148,19 @@
 Diag << CastType;
 ReplaceWithCast((CastType + "<" + DestTypeString + ">").str());
   };
-
+  auto ReplaceWithConstructorCall = [&]() { 
+Diag << "constructor call syntax";
+// FIXME: Validate DestTypeString, maybe.
+ReplaceWithCast(DestTypeString.str());
+  };
   // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics.
   switch (CastExpr->getCastKind()) {
   case CK_FunctionToPointerDecay:
 ReplaceWithNamedCast("static_cast");
 return;
   case CK_ConstructorConversion:
-if (!CastExpr->getTypeAsWritten().hasQualifiers() &&
-DestTypeAsWritten->isRecordType() &&
-!DestTypeAsWritten->isElaboratedTypeSpecifier()) {
-  Diag << "constructor call syntax";
-  // FIXME: Validate DestTypeString, maybe.
-  ReplaceWithCast(DestTypeString.str());
+if (ConstructorCast) {
+  ReplaceWithConstructorCall();
 } else {
   ReplaceWithNamedCast("static_cast");
 }
@@ -176,6 +180,10 @@
   ReplaceWithNamedCast("const_cast");
   return;
 }
+if (ConstructorCast) {
+  ReplaceWithConstructorCall();
+  return;
+}
 if (DestType->isReferenceType()) {
   QualType Dest = DestType.getNonReferenceType();
   QualType Source = SourceType.getNonReferenceType();


Index: clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
===
--- clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
+++ clang-tools-extra/test/clang-tidy/google-readability-casting.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s google-readability-casting %t
+// RUN: %check_clang_tidy -std=c++11-or-later %s google-readability-casting %t
 // FIXME: Fix the checker to work in C++17 mode.
 
 bool g() { return false; }
Index: clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
===
--- clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
+++ clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp
@@ -86,6 +86,10 @@
   bool FnToFnCast =
   isFunction(SourceTypeAsWritten) && isFunction(DestTypeAsWritten);
 
+  const bool ConstructorCast = !CastExpr->getTypeAsWritten().hasQualifiers() &&
+  DestTypeAsWritten->isRecordType() &&
+  !DestTypeAsWritten->isElaboratedTypeSpecifier();
+
   if (CastExpr->getCastKind() == CK_NoOp && !FnToFnCast) {
 // Function pointer/reference casts may be needed to resolve ambiguities in
 // case of overloaded functions, so detection of redundant casts is trickier
@@ -144,19 +148,19 @@
 Diag << CastType;
 ReplaceWithCast((CastType + "<" + DestTypeString + ">").str());
   };
-
+  auto ReplaceWithConstructorCall = [&]() { 
+Diag << "constructor call syntax";
+// FIXME: Validate DestTypeString, maybe.
+ReplaceWithCast(DestTypeString.str());
+  };
   // Suggest appropriate C++ cast. See [expr.cast] for cast notation semantics.
   switch (CastExpr->getCastKind()) {
   case CK_FunctionToPointerDecay:
 ReplaceWithNamedCast("static_cast");
 return;
   case CK_ConstructorConversion:
-if (!CastExpr->getTypeAsWritten().hasQualifiers() &&
-DestTypeAsWritten->isRecordType() &&
-   

[PATCH] D63221: Fixed clangd diagnostics priority

2019-06-12 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63221

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1,3 +1,4 @@
+
 //===--- DiagnosticsTests.cpp *- 
C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -102,11 +103,22 @@
 if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
   FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
+  // If the token at location is not a comment, use the token.
+  // Otherwise use zero width insertion range
   auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
+  if (R.isValid()) {
+// check if token at location is a priority i.e. not a comment
+Token token;
+bool isTokenPriority = false;
+if(!Lexer::getRawToken(Loc, token, M, L, true))
+  isTokenPriority = token.getKind() != tok::comment;
+if (isTokenPriority) {}
+else if (!isTokenPriority && FallbackRange)
+  return *FallbackRange;
+  }
+  else if (FallbackRange)
+return *FallbackRange;
+  else // Fall back to location only, let the editor deal with it.
 R = CharSourceRange::getCharRange(Loc);
   return halfOpenToRange(M, R);
 }


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1,3 +1,4 @@
+
 //===--- DiagnosticsTests.cpp *- C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in 

[PATCH] D63222: [Clangd] Fixed clangd diagnostics priority

2019-06-12 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

- Fixed diagnostics where zero width inserted ranges were being used instead of 
the whole token
  - Added unit tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63222

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1,3 +1,4 @@
+
 //===--- DiagnosticsTests.cpp *- 
C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -102,11 +103,21 @@
 if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
   FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
+  // If the token at location is not a comment, use the token.
+  // Otherwise use zero width insertion range
   auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
+  if (R.isValid()) {
+// check if token at location is a priority i.e. not a comment
+Token token;
+bool isTokenPriority = false;
+if(!Lexer::getRawToken(Loc, token, M, L, true))
+  isTokenPriority = token.getKind() != tok::comment;
+if (!isTokenPriority && FallbackRange)
+  return *FallbackRange;
+  }
+  else if (FallbackRange)
+return *FallbackRange;
+  else // Fall back to location only, let the editor deal with it.
 R = CharSourceRange::getCharRange(Loc);
   return halfOpenToRange(M, R);
 }


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -1,3 +1,4 @@
+
 //===--- DiagnosticsTests.cpp *- C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomem

[PATCH] D63222: [Clangd] Fixed clangd diagnostics priority

2019-06-12 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 204351.
SureYeaah added a comment.

Remove extra newline


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D63222

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -102,11 +103,21 @@
 if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
   FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
+  // If the token at location is not a comment, use the token.
+  // Otherwise use zero width insertion range
   auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
+  if (R.isValid()) {
+// check if token at location is a priority i.e. not a comment
+Token token;
+bool isTokenPriority = false;
+if(!Lexer::getRawToken(Loc, token, M, L, true))
+  isTokenPriority = token.getKind() != tok::comment;
+if (!isTokenPriority && FallbackRange)
+  return *FallbackRange;
+  }
+  else if (FallbackRange)
+return *FallbackRange;
+  else // Fall back to location only, let the editor deal with it.
 R = CharSourceRange::getCharRange(Loc);
   return halfOpenToRange(M, R);
 }


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +102,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +114,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +139,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '")

[PATCH] D63222: [Clangd] Fixed clangd diagnostics priority

2019-06-13 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 204467.
SureYeaah added a comment.

Refactored code as pointed out by @kadircet


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D63222

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -102,12 +103,18 @@
 if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
   FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
-  auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
-R = CharSourceRange::getCharRange(Loc);
+  // If we can't get the token at the location, fall back to using the location
+  // and let the editor deal with it.
+  auto R = CharSourceRange::getCharRange(Loc);
+  Token Tok;
+  if(!Lexer::getRawToken(Loc, Tok, M, L, true)) {
+bool IsTokenComment = Tok.isNot(tok::comment);
+// If the token at the location is a comment, just use the location.
+// Otherwise use the token.
+if (!IsTokenComment && FallbackRange)
+  return *FallbackRange;
+else R = CharSourceRange::getTokenRange(Tok.getLocation(), 
Tok.getEndLoc());
+  }
   return halfOpenToRange(M, R);
 }
 


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'e

[PATCH] D63222: [Clangd] Fixed clangd diagnostics priority

2019-06-13 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 204489.
SureYeaah marked 4 inline comments as done.
SureYeaah added a comment.

Simplified logic for diagnostics range.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D63222

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -90,24 +91,22 @@
 if (locationInRange(Loc, R, M))
   return halfOpenToRange(M, R);
   }
-  llvm::Optional FallbackRange;
   // The range may be given as a fixit hint instead.
   for (const auto &F : D.getFixItHints()) {
 auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
 if (locationInRange(Loc, R, M))
   return halfOpenToRange(M, R);
-// If there's a fixit that performs insertion, it has zero-width. Therefore
-// it can't contain the location of the diag, but it might be possible that
-// this should be reported as range. For example missing semicolon.
-if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
-  FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
-  auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
-R = CharSourceRange::getCharRange(Loc);
+  // If there's a fixit that performs insertion, it has zero-width. Therefore
+  // it can't contain the location of the diag, but it might be possible that
+  // this should be reported as range. For example missing semicolon.
+  // If the token at the location is not a comment, use the token.
+  // If we can't get the token at the location, fall back to using the location
+  auto R = CharSourceRange::getCharRange(Loc);
+  Token Tok;
+  if(!Lexer::getRawToken(Loc, Tok, M, L, true) && Tok.isNot(tok::comment)) {
+R = CharSourceRange::getTokenRange(Tok.getLocation(), Tok.getEndLoc());
+  }
   return halfOpenToRange(M, R);
 }
 


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@

[PATCH] D63222: [Clangd] Fixed clangd diagnostics priority

2019-06-13 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 204494.
SureYeaah marked 2 inline comments as done.
SureYeaah added a comment.

Formatted code


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D63222

Files:
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@
"of type 'const char [4]'"),
   Diag(Test.range("nomember"), "no member named 'y' in 'Foo'"),
   Diag(Test.range("nomembernamespace"),
-   "no member named 'test' in namespace 'test'")));
+   "no member named 'test' in namespace 'test'"),
+  // We make sure here that the entire token is highlighted
+  AllOf(Diag(Test.range("constructor"),
+ "single-argument constructors must be marked explicit to "
+ "avoid unintentional implicit conversions"),
+WithFix(Fix(Test.range("explicit"), "explicit ",
+"insert 'explicit '");
 }
 
 TEST(DiagnosticsTest, FlagsMatter) {
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
+#include "clang/Lex/Token.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -90,24 +91,22 @@
 if (locationInRange(Loc, R, M))
   return halfOpenToRange(M, R);
   }
-  llvm::Optional FallbackRange;
   // The range may be given as a fixit hint instead.
   for (const auto &F : D.getFixItHints()) {
 auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L);
 if (locationInRange(Loc, R, M))
   return halfOpenToRange(M, R);
-// If there's a fixit that performs insertion, it has zero-width. Therefore
-// it can't contain the location of the diag, but it might be possible that
-// this should be reported as range. For example missing semicolon.
-if (R.getBegin() == R.getEnd() && Loc == R.getBegin())
-  FallbackRange = halfOpenToRange(M, R);
   }
-  if (FallbackRange)
-return *FallbackRange;
-  // If no suitable range is found, just use the token at the location.
-  auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L);
-  if (!R.isValid()) // Fall back to location only, let the editor deal with it.
-R = CharSourceRange::getCharRange(Loc);
+  // If there's a fixit that performs insertion, it has zero-width. Therefore
+  // it can't contain the location of the diag, but it might be possible that
+  // this should be reported as range. For example missing semicolon.
+  // If the token at the location is not a comment, we use the token.
+  // If we can't get the token at the location, fall back to using the location
+  auto R = CharSourceRange::getCharRange(Loc);
+  Token Tok;
+  if (!Lexer::getRawToken(Loc, Tok, M, L, true) && Tok.isNot(tok::comment)) {
+R = CharSourceRange::getTokenRange(Tok.getLocation(), Tok.getEndLoc());
+  }
   return halfOpenToRange(M, R);
 }
 


Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
===
--- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -101,6 +101,7 @@
   Annotations Test(R"cpp(
 namespace test{};
 void $decl[[foo]]();
+class T{$explicit[[]]$constructor[[T]](int a);};
 int main() {
   $typo[[go\
 o]]();
@@ -112,8 +113,10 @@
   test::$nomembernamespace[[test]];
 }
   )cpp");
+  auto TU = TestTU::withCode(Test.code());
+  TU.ClangTidyChecks = "-*,google-explicit-constructor";
   EXPECT_THAT(
-  TestTU::withCode(Test.code()).build().getDiagnostics(),
+  TU.build().getDiagnostics(),
   ElementsAre(
   // This range spans lines.
   AllOf(Diag(Test.range("typo"),
@@ -135,7 +138,13 @@
"of t

[PATCH] D64562: [clangd] Fixed toHalfOpenFileRange

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209363.
SureYeaah marked 12 inline comments as done.
SureYeaah added a comment.

Added comments and minor changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64562

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

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -10,6 +10,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "TestTU.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Format/Format.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_os_ostream.h"
@@ -421,6 +422,53 @@
   EXPECT_THAT(*Result, MacroName("MACRO"));
 }
 
+// Test for functions toHalfOpenFileRange and getHalfOpenFileRange
+// FIXME: Need better testing support to be able to check more than just Decls.
+// e.g. TemplateSpecializationTypeLoc SourceRange in nested templates.
+TEST(SourceCodeTests, HalfOpenFileRange) {
+  // Each marked range should be the file range of the decl with the same name
+  // and each name should be unique.
+  Annotations Test(R"cpp(
+#define FOO(X, Y) int Y = ++X
+#define BAR(X) X + 1
+#define ECHO(X) X
+template
+class P {};
+void f() {
+  $a[[P a]];
+  $b[[int b = 1]];
+  $c[[FOO(b, c)]]; 
+  $d[[FOO(BAR(BAR(b)), d)]];
+  // FIXME: We might want to select everything inside the outer ECHO.
+  ECHO(ECHO($e[[int) ECHO(e]]));
+}
+  )cpp");
+
+  ParsedAST AST = TestTU::withCode(Test.code()).build();
+  llvm::errs() << Test.code();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+  // Turn a SourceLocation into a pair of positions
+  auto SourceRangeToRange = [&SM](SourceRange SrcRange) {
+return Range{sourceLocToPosition(SM, SrcRange.getBegin()),
+ sourceLocToPosition(SM, SrcRange.getEnd())};
+  };
+  auto CheckRange = [&](llvm::StringRef Name) {
+const NamedDecl &Decl = findUnqualifiedDecl(AST, Name);
+auto FileRange = toHalfOpenFileRange(SM, LangOpts, Decl.getSourceRange());
+SCOPED_TRACE("Checking range: " + Name);
+ASSERT_NE(FileRange, llvm::None);
+Range HalfOpenRange = SourceRangeToRange(*FileRange);
+EXPECT_EQ(HalfOpenRange, Test.ranges(Name)[0]);
+  };
+
+  CheckRange("a");
+  CheckRange("b");
+  CheckRange("c");
+  CheckRange("d");
+  CheckRange("e");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,9 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/SHA1.h"
 
 namespace clang {
 class SourceManager;
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,8 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -244,20 +246,106 @@
   return L == R.getEnd() || halfOpenRangeContains(Mgr, R, L);
 }
 
-llvm::Optional toHalfOpenFileRange(const SourceManager &Mgr,
+static unsigned getTokenLengthAtLoc(SourceLocation Loc, const SourceManager &SM,
+const LangOptions &LangOpts) {
+  Token TheTok;
+  if (Lexer::getRawToken(Loc, TheTok, SM, LangOpts))
+return 0;
+  // FIXME: Here we check whether the token at the location is a greatergreater
+  // (>>) token and consider it as a single greater (>). This is to get it
+  // working for templates but it isn't correct for the right shift operator. We
+  // can avoid this by using half open char ranges in getFileRange() but getting
+  // token ending is not well supported in macroIDs.
+  if (TheTok.is(tok::greatergreater))
+return 1;
+  return TheTok.getLength();
+}
+
+// Returns location of the last character of the token at a given loc
+static SourceLocation getLocForTokenEnd(SourceLocation BeginLoc,
+const SourceManager &SM,
+const LangOptions &LangOpts) {
+  unsigned Len = getTokenLengthAtLoc(BeginLoc, SM, LangOpts);
+  return BeginLoc.g

[PATCH] D64562: [clangd] Fixed toHalfOpenFileRange

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp:410
+// Test for functions toHalfOpenFileRange and getHalfOpenFileRange
+// FIXME: Need better testing support to be able to check more than just Decls.
+TEST(SourceCodeTests, HalfOpenFileRange) {

sammccall wrote:
> this is a function on ranges, so only using decls isn't a limitation per se.
> 
> Is there a type of range you're unable to test because you can't construct it 
> as the source range of a decl? If so, please say which. If not I think we 
> should just drop this comment.
e.g. Nested template instantiation (TemplateSpecializationTypeLoc)



Comment at: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp:421
+  $c[[FOO(b, c)]]; 
+  $d[[FOO(BAR(BAR(b)), d)]];
+}

sammccall wrote:
> some tests where the expansion range is a macro arg? e.g.
> ```
> #define ECHO(X) X
> ECHO($e[[ECHO(int) ECHO(e)]])
> ```
> 
> (if I'm understanding right)
In this case, the FileRange would be

```
ECHO(ECHO($e[[int) ECHO(e]]));
```

So the code works correctly. But it's not how we want it to behave right?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64562



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


[PATCH] D64562: [clangd] Fixed toHalfOpenFileRange

2019-07-12 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL365894: [clangd] Fixed toHalfOpenFileRange (authored by 
SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D64562?vs=209363&id=209462#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D64562

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

Index: clang-tools-extra/trunk/clangd/SourceCode.cpp
===
--- clang-tools-extra/trunk/clangd/SourceCode.cpp
+++ clang-tools-extra/trunk/clangd/SourceCode.cpp
@@ -12,6 +12,8 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -244,20 +246,106 @@
   return L == R.getEnd() || halfOpenRangeContains(Mgr, R, L);
 }
 
-llvm::Optional toHalfOpenFileRange(const SourceManager &Mgr,
+static unsigned getTokenLengthAtLoc(SourceLocation Loc, const SourceManager &SM,
+const LangOptions &LangOpts) {
+  Token TheTok;
+  if (Lexer::getRawToken(Loc, TheTok, SM, LangOpts))
+return 0;
+  // FIXME: Here we check whether the token at the location is a greatergreater
+  // (>>) token and consider it as a single greater (>). This is to get it
+  // working for templates but it isn't correct for the right shift operator. We
+  // can avoid this by using half open char ranges in getFileRange() but getting
+  // token ending is not well supported in macroIDs.
+  if (TheTok.is(tok::greatergreater))
+return 1;
+  return TheTok.getLength();
+}
+
+// Returns location of the last character of the token at a given loc
+static SourceLocation getLocForTokenEnd(SourceLocation BeginLoc,
+const SourceManager &SM,
+const LangOptions &LangOpts) {
+  unsigned Len = getTokenLengthAtLoc(BeginLoc, SM, LangOpts);
+  return BeginLoc.getLocWithOffset(Len ? Len - 1 : 0);
+}
+
+// Returns location of the starting of the token at a given EndLoc
+static SourceLocation getLocForTokenBegin(SourceLocation EndLoc,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  return EndLoc.getLocWithOffset(
+  -(signed)getTokenLengthAtLoc(EndLoc, SM, LangOpts));
+}
+
+// Converts a char source range to a token range.
+static SourceRange toTokenRange(CharSourceRange Range, const SourceManager &SM,
+const LangOptions &LangOpts) {
+  if (!Range.isTokenRange())
+Range.setEnd(getLocForTokenBegin(Range.getEnd(), SM, LangOpts));
+  return Range.getAsRange();
+}
+// Returns the union of two token ranges.
+// To find the maximum of the Ends of the ranges, we compare the location of the
+// last character of the token.
+static SourceRange unionTokenRange(SourceRange R1, SourceRange R2,
+   const SourceManager &SM,
+   const LangOptions &LangOpts) {
+  SourceLocation E1 = getLocForTokenEnd(R1.getEnd(), SM, LangOpts);
+  SourceLocation E2 = getLocForTokenEnd(R2.getEnd(), SM, LangOpts);
+  return SourceRange(std::min(R1.getBegin(), R2.getBegin()),
+ E1 < E2 ? R2.getEnd() : R1.getEnd());
+}
+
+// Returns the tokenFileRange for a given Location as a Token Range
+// This is quite similar to getFileLoc in SourceManager as both use
+// getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
+// However:
+// - We want to maintain the full range information as we move from one file to
+//   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
+// - We want to split '>>' tokens as the lexer parses the '>>' in template
+//   instantiations as a '>>' instead of a '>'.
+// There is also getExpansionRange but it simply calls
+// getImmediateExpansionRange on the begin and ends separately which is wrong.
+static SourceRange getTokenFileRange(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+  SourceRange FileRange = Loc;
+  while (!FileRange.getBegin().isFileID()) {
+assert(!FileRange.getEnd().isFileID() &&
+   "Both Begin and End should be MacroIDs.");
+if (SM.isMacroArgExpansion(FileRange.getBegin())) {
+  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
+  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
+} else {
+  SourceRange ExpansionRangeForBegin = toTokenRang

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-12 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209506.
SureYeaah added a comment.

Added a test case


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/unittests/SelectionTests.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
@@ -395,12 +395,23 @@
}
  })cpp"},*/
   // ensure InsertionPoint isn't inside a macro
-  {R"cpp(#define LOOP(x) {int a = x + 1;}
+  // FIXME: SelectionTree needs to be fixed for macros
+  /*{R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
if(1)
 LOOP(5 + ^3)
  })cpp",
-   R"cpp(#define LOOP(x) {int a = x + 1;}
+ 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) do {x;} while(1);
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) do {x;} while(1);
  void f(int a) {
auto dummy = 3; if(1)
 LOOP(5 + dummy)
@@ -421,9 +432,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Doesn't work correctly for this code since the attr is
+  // inside the DeclStmt and the bounds of DeclStmt don't cover the attr
+  // \[\[clang::uninitialized\]\] int b = 1;
   };
   for (const auto &IO : InputOutputs) {
 checkTransform(ID, IO.first, IO.second);
Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,15 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
-  SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  auto FileRange =
+  toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());
+  assert(FileRange && "We should be able to get the File Range");
+  return Range{
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +144,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,7 +308,12 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
+  )cpp",
+  R"cpp(int a = [[5 >^> 1]];)cpp",
+  R"cpp(
+#define ECHO(X) X
+ECHO(EC^HO([[$C[[int]]) EC^HO(a]]));
   )cpp",
   };
   for (const char *C : Cases) {
Index: clang-tools-extra/clangd/Selection.cpp
===
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -8,10 +8,13 @@
 
 #include "Selection.h"
 #include "ClangdUnit.h"
+#include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/PrettyPrint

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

- Modified ExtractVariable to stop extraction for MemberExprs and

Assignment Expr

- Fixed unittests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -299,32 +299,32 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 * [[xyz();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]]) {}
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[6]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]]+4]]; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a++]];
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -77,14 +77,20 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
+// An expr is not extractable if it's null, expression of type void, an
+// assignment expression, Member or a DeclRefExpr
 static bool isExtractableExpr(const clang::Expr *Expr) {
   if (Expr) {
-const Type *ExprType = Expr->getType().getTypePtrOrNull();
 // FIXME: check if we need to cover any other types
-if (ExprType)
-  return !ExprType->isVoidType();
+if(const Type *ExprType = Expr->getType().getTypePtrOrNull())
+  if(ExprType->isVoidType())
+return false;
+if(const BinaryOperator *BinOpExpr = llvm::dyn_cast_or_null(Expr))
+  if(BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+return false;
+if(llvm::isa(Expr) || llvm::isa(Expr))
+return false;
+return true;
   }
   return false;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209809.
SureYeaah added a comment.

Fixed comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -299,32 +299,32 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 * [[xyz();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]]) {}
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[6]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]]+4]]; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a++]];
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -77,14 +77,21 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
+// An expr is not extractable if it's null, an expression of type void, an
+// assignment expression, MemberExpr or a DeclRefExpr
 static bool isExtractableExpr(const clang::Expr *Expr) {
   if (Expr) {
-const Type *ExprType = Expr->getType().getTypePtrOrNull();
 // FIXME: check if we need to cover any other types
-if (ExprType)
-  return !ExprType->isVoidType();
+if (const Type *ExprType = Expr->getType().getTypePtrOrNull())
+  if (ExprType->isVoidType())
+return false;
+if (const BinaryOperator *BinOpExpr =
+llvm::dyn_cast_or_null(Expr))
+  if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+return false;
+if (llvm::isa(Expr) || llvm::isa(Expr))
+  return false;
+return true;
   }
   return false;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209844.
SureYeaah marked 5 inline comments as done.
SureYeaah added a comment.

Removed unrelated changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -299,10 +299,10 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 ^* xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -320,7 +320,7 @@
 a = ^2;
   // while 
   while(a < ^1)
-^a++;
+[[a++]];
   // do while 
   do
 a = ^1;
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -77,16 +77,22 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
+// An expr is not extractable if it's null, an expression of type void, an
+// assignment expression, MemberExpr or a DeclRefExpr
 static bool isExtractableExpr(const clang::Expr *Expr) {
-  if (Expr) {
-const Type *ExprType = Expr->getType().getTypePtrOrNull();
-// FIXME: check if we need to cover any other types
-if (ExprType)
-  return !ExprType->isVoidType();
-  }
-  return false;
+  if (!Expr)
+return false;
+  // FIXME: check if we need to cover any other types
+  if (const Type *ExprType = Expr->getType().getTypePtrOrNull())
+if (ExprType->isVoidType())
+  return false;
+  if (const BinaryOperator *BinOpExpr =
+  llvm::dyn_cast_or_null(Expr))
+if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+  return false;
+  if (llvm::isa(Expr) || llvm::isa(Expr))
+return false;
+  return true;
 }
 
 ExtractionContext::ExtractionContext(const SelectionTree::Node *Node,


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -299,10 +299,10 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 ^* xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -320,7 +320,7 @@
 a = ^2;
   // while 
   while(a < ^1)
-^a++;
+[[a++]];
   // do while 
   do
 a = ^1;
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -77,16 +77,22 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
+// An expr is not extractable if it's null, an expression of type void, an
+// assignment expression, MemberExpr or a DeclRefExpr
 static bool isExtractableExpr(const

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:299
   // return statement
   return ^1;
 }

kadircet wrote:
> left out this one ?
Since that's an IntegerLiteral, this patch doesn't apply to it?



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:302
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 * [[xyz();
   // multivariable initialization

kadircet wrote:
> kadircet wrote:
> > how come these changes part of that patch?
> > 
> > is it possible that this tweak was changed to not trigger on empty 
> > selections, but tests were not updated? If that's the case could you please 
> > send these on a different patch and rebase this patch on that one?
> > how come these changes part of that patch?
> 
> how come these changes *are* part of that patch?
> 
> 
This patch doesn't involve empty selection triggers. Reverted these changes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added a comment.

In D64717#1585512 , @sammccall wrote:

> Are you sure we want to disable extraction here, rather than just do the 
> extraction at a higher level?
>
> E.g. if `bar(1,2,3, f[[o]]o(4,5));` seems like it should extract the call too 
> `foo(4,5)`, not fail to trigger entirely.


Selecting `f[[o]]o(4,5)` will just extract the `foo` which would be a 
`DeclRefExpr`. We want to extract the `CallExpr` for which we would need to 
select the brackets as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked an inline comment as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:323
   while(a < ^1)
-^a++;
+[[a++]];
   // do while 

kadircet wrote:
> I thought extractor didn't handle this case(missing braces).
> 
> What is the extraction in this case? Because if it is
> 
> ```
> auto dummy = a++;
> while (a < 1)
>dummy++;
> ```
> 
> it is not going to be semantically same.
We don't check for missing braces and continuing traversing up the AST until we 
find the CompoundStmt. 

Yes, it's not going to be semantically the same. We only check if after 
extraction, the extracted expression will reference a variable that hasn't been 
declared till that point.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209853.
SureYeaah marked 2 inline comments as done.
SureYeaah added a comment.

Added comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -299,10 +299,10 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 ^* xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -320,7 +320,7 @@
 a = ^2;
   // while 
   while(a < ^1)
-^a++;
+[[a++]];
   // do while 
   do
 a = ^1;
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -77,16 +77,25 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
+// Decide which types of Exprs are allowed for extraction
 static bool isExtractableExpr(const clang::Expr *Expr) {
-  if (Expr) {
-const Type *ExprType = Expr->getType().getTypePtrOrNull();
-// FIXME: check if we need to cover any other types
-if (ExprType)
-  return !ExprType->isVoidType();
-  }
-  return false;
+  if (!Expr)
+return false;
+  // Expressions with type void can't be assigned.
+  // FIXME: check if we need to cover any other types
+  if (const Type *ExprType = Expr->getType().getTypePtrOrNull())
+if (ExprType->isVoidType())
+  return false;
+  // Extracting Exprs like a = 1 gives dummy = a = 1 which isn't useful.
+  if (const BinaryOperator *BinOpExpr =
+  llvm::dyn_cast_or_null(Expr))
+if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+  return false;
+  // Extracting just a = [[b]] or a = [[foo]]() isn't that useful.
+  // Extracting [[Foo.bar]]() is neither legal nor useful.
+  if (llvm::isa(Expr) || llvm::isa(Expr))
+return false;
+  return true;
 }
 
 ExtractionContext::ExtractionContext(const SelectionTree::Node *Node,
@@ -124,6 +133,7 @@
 
 // FIXME: Extraction from switch and case statements
 // FIXME: Doens't work for FoldExpr
+// FIXME: Ensure extraction from loops doesn't change semantics
 const clang::Stmt *ExtractionContext::computeInsertionPoint() const {
   // returns true if we can extract before InsertionPoint
   auto CanExtractOutside =


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -299,10 +299,10 @@
   return ^1;
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = 5 + [[4 ^* xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -320,7 +320,7 @@
 a = ^2;
   // while 
   while(a < ^1)
-^a++;
+[[a++]];
   // do while 
   do
 a = ^1;
@@ -340,8 +340,10 @@
   return 1;
   class T {
 T(int a = ^1) {};
+T f() { return T(); }
 int xyz = ^1;
   };
+  [[T.[[^t();
 }
 // function default argument
 void f(int b = ^1) {
@@ -359,6 +361,10 @@
 a = ^a ^+ 1;
   // lambda 
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment 
+  [[a ^= 5]];
+  // DeclRefExpr
+  a = [[b]], b = [[xyz]]();
 }
   )cpp");
   // vector of pairs of input and output strings
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
---

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added a comment.

In D64717#1585632 , @sammccall wrote:

> In D64717#1585542 , @SureYeaah wrote:
>
> > In D64717#1585512 , @sammccall 
> > wrote:
> >
> > > Are you sure we want to disable extraction here, rather than just do the 
> > > extraction at a higher level?
> > >
> > > E.g. if `bar(1,2,3, f[[o]]o(4,5));` seems like it should extract the call 
> > > too `foo(4,5)`, not fail to trigger entirely.
> >
> >
> > Selecting `f[[o]]o(4,5)` will just extract the `foo` which would be a 
> > `DeclRefExpr`. We want to extract the `CallExpr` for which we would need to 
> > select the brackets as well.
>
>
> I agree, but this patch doesn't do that. (I think?)
>  Instead it bans extraction entirely in this case.


Yes it doesn't. Our current model doesn't extend the user selection and as such 
we only check the commonAncestor of whatever the user has selected. Should this 
be changed then?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-15 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209922.
SureYeaah added a comment.

Added fix for selecting the callExpr of a MemberExpr/Function DeclRefExpr


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,6 +291,7 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
@@ -302,7 +303,7 @@
   int a = 5 + [[4 ^* ^xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -315,13 +316,13 @@
 a = ^4;
   else
 a = ^5;
-  // for loop 
+  // for loop
   for(a = ^1; a > ^3^+^4; a++)
 a = ^2;
-  // while 
+  // while
   while(a < ^1)
-^a++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = ^1;
   while(a < ^3);
@@ -343,22 +344,28 @@
 int xyz = ^1;
   };
 }
+void v() { return; }
 // function default argument
 void f(int b = ^1) {
   // void expressions
   auto i = new int, j = new int;
   de^lete i^, del^ete j;
+  [[g]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = ^a + 1;
   if(int a = 1)
 if(^a == 4)
   a = ^a ^+ 1;
-  // for loop 
+  // for loop
   for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
 a = ^a ^+ 1;
-  // lambda 
+  // lambda
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment
+  [[a ^= 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -412,6 +419,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f().f]]();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f().f(); return dummy;
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -421,8 +446,8 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = 1;
+  // since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
@@ -37,18 +38,16 @@
 const ASTContext &Ctx);
   const clang::Expr *getExpr() const { return Expr; }
   const SelectionTree::Node *getExprNode() const { return ExprNode; }
-  bool isExtractable() const { return Extractable; }
   // Generate Replacement for replacing selected expression with given VarName
   tooling::Replacement replaceWithVar(llvm::StringRef VarName) const;
   // Generate Replacement for declaring the selected Expr as a new variable
   tooling::Replacement insertDeclaration(llvm::StringRef VarName) const;
+  const clang::Stmt *InsertionPoint = nullptr;
 
 private:
-  bool Extractable = false;
   const clang::Expr *Expr;
   const SelectionTree::Node *ExprNode;
   // Stmt before which we will extract
-  const clang

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-16 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210045.
SureYeaah added a comment.

Fixed wrong function name


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,6 +291,7 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
@@ -302,7 +303,7 @@
   int a = 5 + [[4 ^* ^xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -315,13 +316,13 @@
 a = ^4;
   else
 a = ^5;
-  // for loop 
+  // for loop
   for(a = ^1; a > ^3^+^4; a++)
 a = ^2;
-  // while 
+  // while
   while(a < ^1)
-^a++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = ^1;
   while(a < ^3);
@@ -343,22 +344,28 @@
 int xyz = ^1;
   };
 }
+void v() { return; }
 // function default argument
 void f(int b = ^1) {
   // void expressions
   auto i = new int, j = new int;
   de^lete i^, del^ete j;
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = ^a + 1;
   if(int a = 1)
 if(^a == 4)
   a = ^a ^+ 1;
-  // for loop 
+  // for loop
   for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
 a = ^a ^+ 1;
-  // lambda 
+  // lambda
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment
+  [[a ^= 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -412,6 +419,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f().f]]();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f().f(); return dummy;
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -421,8 +446,8 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = 1;
+  // since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
@@ -37,18 +38,16 @@
 const ASTContext &Ctx);
   const clang::Expr *getExpr() const { return Expr; }
   const SelectionTree::Node *getExprNode() const { return ExprNode; }
-  bool isExtractable() const { return Extractable; }
   // Generate Replacement for replacing selected expression with given VarName
   tooling::Replacement replaceWithVar(llvm::StringRef VarName) const;
   // Generate Replacement for declaring the selected Expr as a new variable
   tooling::Replacement insertDeclaration(llvm::StringRef VarName) const;
+  const clang::Stmt *InsertionPoint = nullptr;
 
 private:
-  bool Extractable = false;
   const clang::Expr *Expr;
   const SelectionTree::Node *ExprNode;
   // Stmt before which we will extract
-  const clang::Stmt *InsertionPoint = nullptr;
   const Sourc

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-16 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210047.
SureYeaah added a comment.

Fixed crash


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,6 +291,7 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
@@ -302,7 +303,7 @@
   int a = 5 + [[4 ^* ^xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -315,13 +316,13 @@
 a = ^4;
   else
 a = ^5;
-  // for loop 
+  // for loop
   for(a = ^1; a > ^3^+^4; a++)
 a = ^2;
-  // while 
+  // while
   while(a < ^1)
-^a++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = ^1;
   while(a < ^3);
@@ -343,22 +344,28 @@
 int xyz = ^1;
   };
 }
+void v() { return; }
 // function default argument
 void f(int b = ^1) {
   // void expressions
   auto i = new int, j = new int;
   de^lete i^, del^ete j;
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = ^a + 1;
   if(int a = 1)
 if(^a == 4)
   a = ^a ^+ 1;
-  // for loop 
+  // for loop
   for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
 a = ^a ^+ 1;
-  // lambda 
+  // lambda
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment
+  [[a ^= 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -412,6 +419,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f().f]]();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f().f(); return dummy;
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -421,8 +446,8 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = 1;
+  // since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
@@ -37,18 +38,16 @@
 const ASTContext &Ctx);
   const clang::Expr *getExpr() const { return Expr; }
   const SelectionTree::Node *getExprNode() const { return ExprNode; }
-  bool isExtractable() const { return Extractable; }
   // Generate Replacement for replacing selected expression with given VarName
   tooling::Replacement replaceWithVar(llvm::StringRef VarName) const;
   // Generate Replacement for declaring the selected Expr as a new variable
   tooling::Replacement insertDeclaration(llvm::StringRef VarName) const;
+  const clang::Stmt *InsertionPoint = nullptr;
 
 private:
-  bool Extractable = false;
   const clang::Expr *Expr;
   const SelectionTree::Node *ExprNode;
   // Stmt before which we will extract
-  const clang::Stmt *InsertionPoint = nullptr;
   const SourceManager &SM;

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: kadircet, sammccall.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

- For now, we don't trigger in any case if it's an empty selection
- Fixed unittests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/clangd/refactor/Tweak.cpp
  clang-tools-extra/clangd/refactor/Tweak.h
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,29 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if(^a == 4)
-  a = ^a ^+ 1;
+if([[a]] == 4)
+  a = a]] +]] 1;
   // for loop 
-  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
-a = ^a ^+ 1;
+  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+a = [[a + 1]];
   // lambda 
-  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -398,7 +399,7 @@
   {R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
if(1)
-LOOP(5 + ^3)
+LOOP(5 + [[3]])
  })cpp",
R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
@@ -407,7 +408,7 @@
  })cpp"},
   // label and attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
@@ -415,14 +416,14 @@
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
-   PLUS(^a);
+   PLUS([[a]]);
  })cpp",
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
+  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +2

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210526.
SureYeaah added a comment.

Added tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/clangd/refactor/Tweak.cpp
  clang-tools-extra/clangd/refactor/Tweak.h
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,31 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
+  // empty selection
+  int a = ^1 ^+ ^2;
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if(^a == 4)
-  a = ^a ^+ 1;
+if([[a]] == 4)
+  a = a]] +]] 1;
   // for loop 
-  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
-a = ^a ^+ 1;
+  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+a = [[a + 1]];
   // lambda 
-  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -398,7 +401,7 @@
   {R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
if(1)
-LOOP(5 + ^3)
+LOOP(5 + [[3]])
  })cpp",
R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
@@ -407,7 +410,7 @@
  })cpp"},
   // label and attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
@@ -415,14 +418,14 @@
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
-   PLUS(^a);
+   PLUS([[a]]);
  })cpp",
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
+  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +219,8 @@
   const ASTContext &Ctx = Inputs.AST.getASTContext();
   const Sour

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked an inline comment as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/Tweak.h:51
+/// The Length of the selection
+unsigned SelectionLength;
 /// The AST nodes that were selected.

kadircet wrote:
> maybe expose a `SourceLocation SelectionEnd` ?
Should I also have a SelectionStart? Or just use Cursor?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64912



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


[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210536.
SureYeaah added a comment.

Added selectionend


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/clangd/refactor/Tweak.cpp
  clang-tools-extra/clangd/refactor/Tweak.h
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,31 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
+  // empty selection
+  int a = ^1 ^+ ^2;
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if(^a == 4)
-  a = ^a ^+ 1;
+if([[a]] == 4)
+  a = a]] +]] 1;
   // for loop 
-  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
-a = ^a ^+ 1;
+  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+a = [[a + 1]];
   // lambda 
-  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -398,7 +401,7 @@
   {R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
if(1)
-LOOP(5 + ^3)
+LOOP(5 + [[3]])
  })cpp",
R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
@@ -407,7 +410,7 @@
  })cpp"},
   // label and attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
@@ -415,14 +418,14 @@
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
-   PLUS(^a);
+   PLUS([[a]]);
  })cpp",
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
+  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +219,8 @@
   const ASTContext &Ctx = Inputs.AST.getASTContext();
   con

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210537.
SureYeaah added a comment.

Fixed comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/clangd/refactor/Tweak.cpp
  clang-tools-extra/clangd/refactor/Tweak.h
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,31 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
+  // empty selection
+  int a = ^1 ^+ ^2;
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if(^a == 4)
-  a = ^a ^+ 1;
+if([[a]] == 4)
+  a = a]] +]] 1;
   // for loop 
-  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
-a = ^a ^+ 1;
+  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+a = [[a + 1]];
   // lambda 
-  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -398,7 +401,7 @@
   {R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
if(1)
-LOOP(5 + ^3)
+LOOP(5 + [[3]])
  })cpp",
R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
@@ -407,7 +410,7 @@
  })cpp"},
   // label and attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
@@ -415,14 +418,14 @@
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
-   PLUS(^a);
+   PLUS([[a]]);
  })cpp",
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
+  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +219,8 @@
   const ASTContext &Ctx = Inputs.AST.getASTContext();
   const So

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked 5 inline comments as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:208
   const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
-  if (!N)
-return false;
-  Target = llvm::make_unique(N, SM, Ctx);
-  return Target->isExtractable();
+  computeExtractionContext(N, SM, Ctx);
+  return Target && Target->InsertionPoint;

kadircet wrote:
> maybe instead of checking internals like `Target` just make 
> `computeExtractionContext` return an `llvm::Error` and check for success?
Should it instead return a bool since there's actually no error?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210545.
SureYeaah added a comment.

Refactored code


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return ^1;
+  return t.bar]](t.z)]];
 }
 void f() {
   int a = 5 + [[4 ^* ^xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -315,13 +320,13 @@
 a = ^4;
   else
 a = ^5;
-  // for loop 
+  // for loop
   for(a = ^1; a > ^3^+^4; a++)
 a = ^2;
-  // while 
+  // while
   while(a < ^1)
-^a++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = ^1;
   while(a < ^3);
@@ -337,28 +342,34 @@
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = ^1) {
-  return 1;
-  class T {
-T(int a = ^1) {};
-int xyz = ^1;
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return t.bar([[t.z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = ^1) {
   // void expressions
   auto i = new int, j = new int;
   de^lete i^, del^ete j;
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = ^a + 1;
   if(int a = 1)
 if(^a == 4)
   a = ^a ^+ 1;
-  // for loop 
+  // for loop
   for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
 a = ^a ^+ 1;
-  // lambda 
+  // lambda
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment
+  [[a ^= 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -412,6 +423,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f().f]]();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f().f(); return dummy;
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -421,8 +450,8 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = 1;
+  // since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
@@ -37,18 +38,16 @@
 const ASTContext &Ctx);
   const clang::Expr *getExpr() const { return Expr; }
   const SelectionTree::Node *getExprNode() const { return ExprNode; }
-  bool isExtractable() const { return Extractable; }
   // Generate Replacement for replacing selected expression with given VarName
   tooling::Replacement replaceWithVar(ll

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:292
+  Target = llvm::make_unique(TargetNode, SM, Ctx);
+  return true;
+}

kadircet wrote:
> `return Target->InsertionPoint`?
Changed to checking if target is extractable.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210560.
SureYeaah marked 4 inline comments as done.
SureYeaah added a comment.

Fixed tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return ^1;
+  return t.b[[a]]r]](t.z)]];
 }
 void f() {
   int a = 5 + [[4 ^* ^xyz^()]];
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = ^1, y = [[a + 1]], a = ^1, z = a + 1;
   // if without else
   if(^1) {}
   // if with else
@@ -315,13 +320,13 @@
 a = ^4;
   else
 a = ^5;
-  // for loop 
+  // for loop
   for(a = ^1; a > ^3^+^4; a++)
 a = ^2;
-  // while 
+  // while
   while(a < ^1)
-^a++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = ^1;
   while(a < ^3);
@@ -337,28 +342,34 @@
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = ^1) {
-  return 1;
-  class T {
-T(int a = ^1) {};
-int xyz = ^1;
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return [[t]].bar(t]].z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = ^1) {
   // void expressions
   auto i = new int, j = new int;
   de^lete i^, del^ete j;
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = ^a + 1;
   if(int a = 1)
 if(^a == 4)
   a = ^a ^+ 1;
-  // for loop 
+  // for loop
   for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
 a = ^a ^+ 1;
-  // lambda 
+  // lambda
   auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  // assigment
+  [[a ^= 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -412,6 +423,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f()]].f();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f(); return dummy.f();
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -421,8 +450,8 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = 1;
+  // since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Stmt.h"
@@ -77,29 +78,15 @@
   return Visitor.ReferencedDecls;
 }
 
-// An expr is not extractable if it's null or an expression of type void
-// FIXME: Ignore assignment (a = 1) Expr since it is extracted as dummy = a =
-static bool isExtractableExpr(const clang::Expr *Expr) {
-  if (Expr) {
-const Type *ExprType = 

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210577.
SureYeaah added a comment.

Added SelectionBegin and SelectionEnd to Tweak::Selection


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/clangd/refactor/Tweak.cpp
  clang-tools-extra/clangd/refactor/Tweak.h
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,31 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
+  // empty selection
+  int a = ^1 ^+ ^2;
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if(^a == 4)
-  a = ^a ^+ 1;
+if([[a]] == 4)
+  a = a]] +]] 1;
   // for loop 
-  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
-a = ^a ^+ 1;
+  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+a = [[a + 1]];
   // lambda 
-  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+  auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -398,7 +401,7 @@
   {R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
if(1)
-LOOP(5 + ^3)
+LOOP(5 + [[3]])
  })cpp",
R"cpp(#define LOOP(x) {int a = x + 1;}
  void f(int a) {
@@ -407,7 +410,7 @@
  })cpp"},
   // label and attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
@@ -415,14 +418,14 @@
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
-   PLUS(^a);
+   PLUS([[a]]);
  })cpp",
R"cpp(#define PLUS(x) x++
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
+  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
+  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
   // DeclStmt don't cover the attribute
   };
   for (const auto &IO : InputOutputs) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +219,8 @@
   const ASTContext &C

[PATCH] D64912: [Clangd] Changed ExtractVariable to only work on non empty selections

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366451: [Clangd] Changed ExtractVariable to only work on non 
empty selections (authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D64912?vs=210577&id=210588#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D64912

Files:
  clang-tools-extra/trunk/clangd/refactor/Tweak.cpp
  clang-tools-extra/trunk/clangd/refactor/Tweak.h
  clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
  clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/trunk/clangd/refactor/Tweak.cpp
===
--- clang-tools-extra/trunk/clangd/refactor/Tweak.cpp
+++ clang-tools-extra/trunk/clangd/refactor/Tweak.cpp
@@ -40,7 +40,8 @@
 
 Tweak::Selection::Selection(ParsedAST &AST, unsigned RangeBegin,
 unsigned RangeEnd)
-: AST(AST), ASTSelection(AST.getASTContext(), RangeBegin, RangeEnd) {
+: AST(AST), SelectionBegin(RangeBegin), SelectionEnd(RangeEnd),
+  ASTSelection(AST.getASTContext(), RangeBegin, RangeEnd) {
   auto &SM = AST.getSourceManager();
   Code = SM.getBufferData(SM.getMainFileID());
   Cursor = SM.getComposedLoc(SM.getMainFileID(), RangeBegin);
Index: clang-tools-extra/trunk/clangd/refactor/Tweak.h
===
--- clang-tools-extra/trunk/clangd/refactor/Tweak.h
+++ clang-tools-extra/trunk/clangd/refactor/Tweak.h
@@ -46,7 +46,12 @@
 /// Parsed AST of the active file.
 ParsedAST &AST;
 /// A location of the cursor in the editor.
+// FIXME: Cursor is redundant and should be removed
 SourceLocation Cursor;
+/// The begin offset of the selection
+unsigned SelectionBegin;
+/// The end offset of the selection
+unsigned SelectionEnd;
 /// The AST nodes that were selected.
 SelectionTree ASTSelection;
 // FIXME: provide a way to get sources and ASTs for other files.
Index: clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -219,7 +219,8 @@
   const ASTContext &Ctx = Inputs.AST.getASTContext();
   const SourceManager &SM = Inputs.AST.getSourceManager();
   const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
-  if (!N)
+  // we don't trigger on empty selections for now
+  if (!N || Inputs.SelectionBegin == Inputs.SelectionEnd)
 return false;
   Target = llvm::make_unique(N, SM, Ctx);
   return Target->isExtractable();
Index: clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
@@ -296,35 +296,36 @@
   checkAvailable(ID, R"cpp(
 int xyz() {
   // return statement
-  return ^1;
+  return [[1]];
 }
 void f() {
-  int a = 5 + [[4 ^* ^xyz^()]];
+  int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
   // if without else
-  if(^1) {}
+  if([[1]])
+a = [[1]];
   // if with else
-  if(a < ^3)
-if(a == ^4)
-  a = ^5;
+  if(a < [[3]])
+if(a == [[4]])
+  a = [[5]];
 else
-  a = ^6;
-  else if (a < ^4)
-a = ^4;
+  a = [[5]];
+  else if (a < [[4]])
+a = [[4]];
   else
-a = ^5;
+a = [[5]];
   // for loop 
-  for(a = ^1; a > ^3^+^4; a++)
-a = ^2;
+  for(a = [[1]]; a > 3]] + [[4; a++)
+a = [[2]];
   // while 
-  while(a < ^1)
-^a++;
+  while(a < [[1]])
+[[a]]++;
   // do while 
   do
-a = ^1;
-  while(a < ^3);
+a = [[1]];
+  while(a < [[3]]);
 }
   )cpp");
   // Should not crash.
@@ -336,29 +337,31 @@
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
-int xyz(int a = ^1) {
+int xyz(int a = [[1]]) {
   return 1;
   class T {
-T(int a = ^1) {};
-int xyz = ^1;
+T(int a = [[1]]) {};
+int xyz = [[1]];
   };
 }
 // function default argument
-void f(int b = ^1) {
+void f(int b = [[1]]) {
+  // empty selection
+  int a = ^1 ^+ ^2;
   // void expressions
   auto i = new int, j = new int;
-  de^lete i^, del^ete j;
+  delete i]], delete j]];
   // if
   if(1)
-int x = 1, y = a + 1, a = 1, z = ^a + 1;
+ 

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-18 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210590.
SureYeaah added a comment.

Merged with trigger on non empty selection only


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return [[1]];
+  return t.b[[a]]r]](t.z)]];
 }
 void f() {
   int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
   if([[1]])
 a = [[1]];
@@ -316,13 +321,13 @@
 a = [[4]];
   else
 a = [[5]];
-  // for loop 
+  // for loop
   for(a = [[1]]; a > 3]] + [[4; a++)
 a = [[2]];
-  // while 
+  // while
   while(a < [[1]])
-[[a]]++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = [[1]];
   while(a < [[3]]);
@@ -332,18 +337,19 @@
   checkNotAvailable(ID, R"cpp(
 template
 struct Test {
-Test(const T &v) :val(^) {}
+Test(const T &v) :val[[(^]]) {}
   T val;
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = [[1]]) {
-  return 1;
-  class T {
-T(int a = [[1]]) {};
-int xyz = [[1]];
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return [[t]].bar(t]].z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = [[1]]) {
   // empty selection
@@ -351,17 +357,22 @@
   // void expressions
   auto i = new int, j = new int;
   delete i]], delete j]];
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if([[a]] == 4)
+if([[a + 1]] == 4)
   a = a]] +]] 1;
-  // for loop 
-  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+  // for loop
+  for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
 a = [[a + 1]];
-  // lambda 
+  // lambda
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
+  // assigment
+  [[a = 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -415,6 +426,24 @@
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f()]].f();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f(); return dummy.f();
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
+ })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
  void f(int a) {
@@ -424,9 +453,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
-  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
+  // since the attr is inside the DeclStmt and the bounds of
+  // DeclStmt don't cover the attribute.
   };
   for (const auto &IO : InputOutputs) {
 checkTransform(ID, IO.first, IO.second);
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -13,6 +13,7 @@
 #include "refactor/Tweak.h"
 #include "clang/AST/ASTCont

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-19 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210783.
SureYeaah marked 2 inline comments as done.
SureYeaah added a comment.

Updated comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/unittests/SelectionTests.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
@@ -395,12 +395,23 @@
}
  })cpp"},*/
   // ensure InsertionPoint isn't inside a macro
-  {R"cpp(#define LOOP(x) {int a = x + 1;}
+  // FIXME: SelectionTree needs to be fixed for macros
+  /*{R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
if(1)
 LOOP(5 + ^3)
  })cpp",
-   R"cpp(#define LOOP(x) {int a = x + 1;}
+ 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) do {x;} while(1);
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) do {x;} while(1);
  void f(int a) {
auto dummy = 3; if(1)
 LOOP(5 + dummy)
@@ -421,9 +432,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Doesn't work correctly for this code since the attr is
+  // inside the DeclStmt and the bounds of DeclStmt don't cover the attr
+  // \[\[clang::uninitialized\]\] int b = 1;
   };
   for (const auto &IO : InputOutputs) {
 checkTransform(ID, IO.first, IO.second);
Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,15 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
-  SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  auto FileRange =
+  toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());
+  assert(FileRange && "We should be able to get the File Range");
+  return Range{
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +144,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -289,6 +289,9 @@
   EXPECT_FALSE(D->isInjectedClassName());
 }
 
+// FIXME: Doesn't select the binary operator node in
+//  #define FOO(X) X + 1
+//  int a, b = [[FOO(a)]];
 TEST(SelectionTest, Selected) {
   // Selection with ^marks^.
   // Partially selected nodes marked with a [[range]].
@@ -308,7 +311,12 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
+  )cpp",
+  R"cpp(int a = [[5 >^> 1]];)cpp",
+  R"cpp(
+#define ECHO(X) X
+ECHO(EC^HO([[$C[[int]]) EC^HO(a]]));
   )cpp",
   };
   for (const char *C : Cases) {
Index: cla

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-19 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL366566: [Clangd] Fixed SelectionTree bug for macros 
(authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D64329?vs=210783&id=210799#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/trunk/clangd/Selection.cpp
  clang-tools-extra/trunk/clangd/unittests/SelectionTests.cpp
  clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/trunk/clangd/Selection.cpp
===
--- clang-tools-extra/trunk/clangd/Selection.cpp
+++ clang-tools-extra/trunk/clangd/Selection.cpp
@@ -8,10 +8,13 @@
 
 #include "Selection.h"
 #include "ClangdUnit.h"
+#include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/STLExtras.h"
 #include 
 
@@ -239,26 +242,23 @@
   SelectionTree::Selection claimRange(SourceRange S) {
 if (!S.isValid())
   return SelectionTree::Unselected;
-// getTopMacroCallerLoc() allows selection of constructs in macro args. e.g:
+// toHalfOpenFileRange() allows selection of constructs in macro args. e.g:
 //   #define LOOP_FOREVER(Body) for(;;) { Body }
 //   void IncrementLots(int &x) {
 // LOOP_FOREVER( ++x; )
 //   }
 // Selecting "++x" or "x" will do the right thing.
-auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
-auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
+auto Range = toHalfOpenFileRange(SM, LangOpts, S);
+assert(Range && "We should be able to get the File Range");
+auto B = SM.getDecomposedLoc(Range->getBegin());
+auto E = SM.getDecomposedLoc(Range->getEnd());
 // Otherwise, nodes in macro expansions can't be selected.
 if (B.first != SelFile || E.first != SelFile)
   return SelectionTree::Unselected;
-// Cheap test: is there any overlap at all between the selection and range?
-// Note that E.second is the *start* of the last token, which is why we
-// compare against the "rounded-down" SelBegin.
-if (B.second >= SelEnd || E.second < SelBeginTokenStart)
+// Is there any overlap at all between the selection and range?
+if (B.second >= SelEnd || E.second < SelBegin)
   return SelectionTree::Unselected;
-
-// We may have hit something, need some more precise checks.
-// Adjust [B, E) to be a half-open character range.
-E.second += Lexer::MeasureTokenLength(S.getEnd(), SM, LangOpts);
+// We may have hit something.
 auto PreciseBounds = std::make_pair(B.second, E.second);
 // Trim range using the selection, drop it if empty.
 B.second = std::max(B.second, SelBegin);
Index: clang-tools-extra/trunk/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,15 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
-  SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  auto FileRange =
+  toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());
+  assert(FileRange && "We should be able to get the File Range");
+  return Range{
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +144,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-19 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210800.
SureYeaah marked 5 inline comments as done.
SureYeaah added a comment.

Minor changes and disabled extraction from label statement


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return [[1]];
+  return t.b[[a]]r]](t.z)]];
 }
 void f() {
   int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
   if([[1]])
 a = [[1]];
@@ -316,13 +321,13 @@
 a = [[4]];
   else
 a = [[5]];
-  // for loop 
+  // for loop
   for(a = [[1]]; a > 3]] + [[4; a++)
 a = [[2]];
-  // while 
+  // while
   while(a < [[1]])
-[[a]]++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = [[1]];
   while(a < [[3]]);
@@ -332,18 +337,19 @@
   checkNotAvailable(ID, R"cpp(
 template
 struct Test {
-Test(const T &v) :val(^) {}
+Test(const T &v) :val[[(^]]) {}
   T val;
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = [[1]]) {
-  return 1;
-  class T {
-T(int a = [[1]]) {};
-int xyz = [[1]];
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return [[t]].bar(t]].z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = [[1]]) {
   // empty selection
@@ -351,17 +357,22 @@
   // void expressions
   auto i = new int, j = new int;
   delete i]], delete j]];
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if([[a]] == 4)
+if([[a + 1]] == 4)
   a = a]] +]] 1;
-  // for loop 
-  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+  // for loop
+  for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
 a = [[a + 1]];
-  // lambda 
+  // lambda
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
+  // assigment
+  [[a = 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -408,12 +419,30 @@
auto dummy = 3; if(1)
 LOOP(5 + dummy)
  })cpp"},
-  // label and attribute testing
+  // attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
+[ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
-auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
+auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy;
+ })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f()]].f();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f(); return dummy.f();
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
  })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
@@ -424,9 +453,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
-  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
+  // since the attr is inside the DeclStmt and the bounds

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-19 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 210803.
SureYeaah marked an inline comment as done.
SureYeaah added a comment.

Added test for label


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return [[1]];
+  return t.b[[a]]r]](t.z)]];
 }
 void f() {
   int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
   if([[1]])
 a = [[1]];
@@ -316,13 +321,13 @@
 a = [[4]];
   else
 a = [[5]];
-  // for loop 
+  // for loop
   for(a = [[1]]; a > 3]] + [[4; a++)
 a = [[2]];
-  // while 
+  // while
   while(a < [[1]])
-[[a]]++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = [[1]];
   while(a < [[3]]);
@@ -332,18 +337,19 @@
   checkNotAvailable(ID, R"cpp(
 template
 struct Test {
-Test(const T &v) :val(^) {}
+Test(const T &v) :val[[(^]]) {}
   T val;
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = [[1]]) {
-  return 1;
-  class T {
-T(int a = [[1]]) {};
-int xyz = [[1]];
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return [[t]].bar(t]].z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = [[1]]) {
   // empty selection
@@ -351,17 +357,26 @@
   // void expressions
   auto i = new int, j = new int;
   delete i]], delete j]];
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if([[a]] == 4)
+if([[a + 1]] == 4)
   a = a]] +]] 1;
-  // for loop 
-  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+  // for loop
+  for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
 a = [[a + 1]];
-  // lambda 
+  // lambda
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
+  // assigment
+  [[a = 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
+  // label statement
+  goto label;
+  label:
+a = [[1]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -408,12 +423,30 @@
auto dummy = 3; if(1)
 LOOP(5 + dummy)
  })cpp"},
-  // label and attribute testing
+  // attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
+[ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
-auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
+auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy;
+ })cpp"},
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f()]].f();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f(); return dummy.f();
+   }
+ };)cpp"},
+  // Function DeclRefExpr
+  {R"cpp(int f() {
+   return [[f]]();
+ })cpp",
+   R"cpp(int f() {
+   auto dummy = f(); return dummy;
  })cpp"},
   // FIXME: Doesn't work because bug in selection tree
   /*{R"cpp(#define PLUS(x) x++
@@ -424,9 +457,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int
-  // b = [[1]]; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Wrong result for \[\[clang::uninitialized\]\] int b = [[1]];
+  // since the a

[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-19 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:427
R"cpp(void f(int a) {
 auto dummy = 1; label: [ [gsl::suppress("type")] ] for 
(;;) a = dummy;
  })cpp"},

kadircet wrote:
> I think `auto dummy = 1;` should be within the label. otherwise we might 
> break codes like(which is basically anything with labels):
> ```
> void foo() {
> goto label;
> label:
>  a = 1;
> }
> ```
> 
> I don't think it is that important though, and have no idea about the effort 
> necessary feel free to just add a FIXME if it turns out hard.
I've disabled extraction from label statements and added a fixme because the 
fix for all kinds of loops as well as if statement needs another patch.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717



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


[PATCH] D64717: [Clangd] Fixed ExtractVariable for MemberExprs and Assignment Exprs

2019-07-23 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb0ed5bea8812: [Clangd] Fixed ExtractVariable for certain 
types of Exprs (authored by SureYeaah).

Changed prior to commit:
  https://reviews.llvm.org/D64717?vs=210803&id=211423#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64717

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -291,18 +291,23 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+
 TEST(TweakTest, ExtractVariable) {
   llvm::StringLiteral ID = "ExtractVariable";
   checkAvailable(ID, R"cpp(
-int xyz() {
+int xyz(int a = 1) {
+  struct T {
+int bar(int a = 1);
+int z;
+  } t;
   // return statement
-  return [[1]];
+  return t.b[[a]]r]](t.z)]];
 }
 void f() {
   int a = [[5 +]] [[4 * xyz]]();
   // multivariable initialization
   if(1)
-int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1;
+int x = [[1]], y = [[a + 1]], a = [[1]], z = a + 1;
   // if without else
   if([[1]])
 a = [[1]];
@@ -316,13 +321,13 @@
 a = [[4]];
   else
 a = [[5]];
-  // for loop 
+  // for loop
   for(a = [[1]]; a > 3]] + [[4; a++)
 a = [[2]];
-  // while 
+  // while
   while(a < [[1]])
-[[a]]++;
-  // do while 
+[[a++]];
+  // do while
   do
 a = [[1]];
   while(a < [[3]]);
@@ -332,18 +337,19 @@
   checkNotAvailable(ID, R"cpp(
 template
 struct Test {
-Test(const T &v) :val(^) {}
+Test(const T &v) :val[[(^]]) {}
   T val;
 };
   )cpp");
   checkNotAvailable(ID, R"cpp(
 int xyz(int a = [[1]]) {
-  return 1;
-  class T {
-T(int a = [[1]]) {};
-int xyz = [[1]];
-  };
+  struct T {
+int bar(int a = [[1]]);
+int z = [[1]];
+  } t;
+  return [[t]].bar(t]].z]]);
 }
+void v() { return; }
 // function default argument
 void f(int b = [[1]]) {
   // empty selection
@@ -351,17 +357,26 @@
   // void expressions
   auto i = new int, j = new int;
   delete i]], delete j]];
+  [[v]]();
   // if
   if(1)
 int x = 1, y = a + 1, a = 1, z = [[a + 1]];
   if(int a = 1)
-if([[a]] == 4)
+if([[a + 1]] == 4)
   a = a]] +]] 1;
-  // for loop 
-  for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++)
+  // for loop
+  for(int a = 1, b = 2, c = 3; a > [[b + c]]; [[a++]])
 a = [[a + 1]];
-  // lambda 
+  // lambda
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
+  // assigment
+  [[a = 5]];
+  // Variable DeclRefExpr
+  a = [[b]];
+  // label statement
+  goto label;
+  label:
+a = [[1]];
 }
   )cpp");
   // vector of pairs of input and output strings
@@ -397,6 +412,15 @@
  break;
}
  })cpp"},*/
+  // Macros
+  {R"cpp(#define PLUS(x) x++
+ void f(int a) {
+   PLUS([[1+a]]);
+ })cpp",
+   R"cpp(#define PLUS(x) x++
+ void f(int a) {
+   auto dummy = PLUS(1+a); dummy;
+ })cpp"},
   // ensure InsertionPoint isn't inside a macro
   {R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
@@ -425,25 +449,35 @@
auto dummy = 3; if(1)
 LOOP(5 + dummy)
  })cpp"},
-  // label and attribute testing
+  // attribute testing
   {R"cpp(void f(int a) {
-label: [ [gsl::suppress("type")] ] for (;;) a = [[1]];
+[ [gsl::suppress("type")] ] for (;;) a = [[1]];
  })cpp",
R"cpp(void f(int a) {
-auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy;
+auto dummy = 1; [ [gsl::suppress("type")] ] for (;;) a = dummy;
  })cpp"},
-  // macro testing
-  {R"cpp(#define PLUS(x) x++
- void f(int a) {
-   PLUS([[a]]);
+  // MemberExpr
+  {R"cpp(class T {
+   T f() {
+ return [[T().f()]].f();
+   }
+ };)cpp",
+   R"cpp(class T {
+   T f() {
+ auto dummy = T().f(); return dummy.f();
+

[PATCH] D65139: [clangd] Support extraction of binary "subexpressions" like a + [[b + c]].

2019-07-24 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:210
+//  - we don't look inside macro expansions in the subexpressions
+//  - we only adjust the extracted range, so references in the unselected parts
+//of the AST expression (e.g. `a`) are still considered referenced for

A related FIXME would be helpful since it's pretty easy to fix(I think?) and 
seems like something important.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:213
+//the purposes of calculating the insertion point.
+namespace {
+

Why do we need an anon namespace inside another anon namespace?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:217
+// It can represent either an overloaded or built-in operator.
+struct ParsedBinaryOperator {
+  BinaryOperatorKind Kind;

Wouldn't it make more sense this to have this in some other place (maybe 
Selection) because other refactorings might want to make use of this feature?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:235
+N.ASTNode.get())) {
+  if (Op->isInfixBinaryOp()) {
+Kind = BinaryOperator::getOverloadedOpcode(Op->getOperator());

Can we negate this if to reduce nesting?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:283
+const SelectionTree::Node *getEndpoint(const SelectionTree::Node &N,
+   BinaryOperatorKind OuterOp, bool 
IsStart,
+   const SourceManager &SM) {

We're considering the case where all the operators are the same. Isn't it true 
that in that case, the End will be the the first 'selected RHS' that we find 
during the traversal? If so, can't we just get rid of the IsStart?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:393
   std::string VarName = "dummy";
+  SourceRange Range = Target->getExtractionChars();
   // insert new variable declaration

Why not just compute this inside ExtractionContext?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65139



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


[PATCH] D65139: [clangd] Support extraction of binary "subexpressions" like a + [[b + c]].

2019-07-25 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:50
   // Generate Replacement for declaring the selected Expr as a new variable
-  tooling::Replacement insertDeclaration(llvm::StringRef VarName) const;
+  tooling::Replacement insertDeclaration(llvm::StringRef VarName,
+ SourceRange InitChars) const;

Nit: same parameter order for replaceWithVar and insertDeclaration.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:245
+assert(E && "callee and args should be Exprs!");
+if (E == Op->getArg(0) || E == Op->getArg(1))
+  SelectedOperands.push_back(Child);

Why do we need to check this for CXXOperatorCallExpr and not BinaryOperator?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:305
+  const SelectionTree::Node *Start = Op.SelectedOperands.front(); // LHS
+  const SelectionTree::Node *End = Op.SelectedOperands.back();// RHS
+  // End is already correct, Start needs to be pushed down to the right spot.

For 1 + [[2 + 3 * 4]] + 5, we probably don't get an invalid range from this 
function. If so, we might want to add one more check where we parse End and 
compare it's operator.





Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:314
+}
+// Op.LHS (partially) selected, so descend into it.
+Start = Op.SelectedOperands.front();

Nit: For [[a + b + c]],

   +
 /  \
+c
   / \
  a   b

For the second + as Op, a would be completely selected. So Op.LHS can be 
partially or completely selected.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:448
+
+  // Binary subexpressions
+  {R"cpp(void f() {

Can we have some tests with macros as well?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65139



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


[PATCH] D65139: [clangd] Support extraction of binary "subexpressions" like a + [[b + c]].

2019-07-26 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:50
   // Generate Replacement for declaring the selected Expr as a new variable
-  tooling::Replacement insertDeclaration(llvm::StringRef VarName) const;
+  tooling::Replacement insertDeclaration(llvm::StringRef VarName,
+ SourceRange InitChars) const;

sammccall wrote:
> SureYeaah wrote:
> > Nit: same parameter order for replaceWithVar and insertDeclaration.
> I think this *is* the same parameter order semantically: this is roughly 
> (thing, definition) in both cases.
> The fact that the *types* match but in the opposite order is just a 
> coincidence I think?
Sorry yes, makes sense.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:305
+  const SelectionTree::Node *Start = Op.SelectedOperands.front(); // LHS
+  const SelectionTree::Node *End = Op.SelectedOperands.back();// RHS
+  // End is already correct, Start needs to be pushed down to the right spot.

sammccall wrote:
> SureYeaah wrote:
> > For 1 + [[2 + 3 * 4]] + 5, we probably don't get an invalid range from this 
> > function. If so, we might want to add one more check where we parse End and 
> > compare it's operator.
> > 
> > 
> I'm not quite sure what you mean here.
> 
> Annotating the operators, for `1 +a [[2 +b 3 *c 4]] +d 5`:
>  - N is `*c`
>  - RHS is `4`
>  - LHS is `1 +a 2 +b 3 *c 4`.
> 
> The point is that RHS can never be an operator of the same type, because if 
> we replaced RHS with `x +e y` then N would be that `+e` instead (since `+` is 
> left-associative).
> 
But isn't the tree something like

+
 /\ 
+ 5
 / \
 +   *
   /  \   /   \
   1234


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65139



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


[PATCH] D65139: [clangd] Support extraction of binary "subexpressions" like a + [[b + c]].

2019-07-26 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:448
+
+  // Binary subexpressions
+  {R"cpp(void f() {

sammccall wrote:
> SureYeaah wrote:
> > Can we have some tests with macros as well?
> Added a simple one that just verifies we support operands being wrapped in 
> macros, but not operators.
Isn't it the same behavior in both cases?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65139



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


[PATCH] D65332: [Clangd] Disable ExtractVariable for all types of assignments

2019-07-26 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65332

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -371,6 +371,8 @@
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
   // assigment
   [[a = 5]];
+  [[a >>= 5]];
+  [[a *= 5]];
   // Variable DeclRefExpr
   a = [[b]];
   // label statement
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -272,7 +272,7 @@
   // Extracting Exprs like a = 1 gives dummy = a = 1 which isn't useful.
   if (const BinaryOperator *BinOpExpr =
   dyn_cast_or_null(SelectedExpr)) {
-if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+if (BinOpExpr->isAssignmentOp())
   return false;
   }
   // For function and member function DeclRefs, we look for a parent that is a


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -371,6 +371,8 @@
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
   // assigment
   [[a = 5]];
+  [[a >>= 5]];
+  [[a *= 5]];
   // Variable DeclRefExpr
   a = [[b]];
   // label statement
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -272,7 +272,7 @@
   // Extracting Exprs like a = 1 gives dummy = a = 1 which isn't useful.
   if (const BinaryOperator *BinOpExpr =
   dyn_cast_or_null(SelectedExpr)) {
-if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+if (BinOpExpr->isAssignmentOp())
   return false;
   }
   // For function and member function DeclRefs, we look for a parent that is a
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65332: [Clangd] Disable ExtractVariable for all types of assignments

2019-07-26 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL367113: [Clangd] Disable ExtractVariable for all types of 
assignments (authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65332?vs=211927&id=211937#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D65332

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


Index: clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -272,7 +272,7 @@
   // Extracting Exprs like a = 1 gives dummy = a = 1 which isn't useful.
   if (const BinaryOperator *BinOpExpr =
   dyn_cast_or_null(SelectedExpr)) {
-if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+if (BinOpExpr->isAssignmentOp())
   return false;
   }
   // For function and member function DeclRefs, we look for a parent that is a
Index: clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
@@ -371,6 +371,8 @@
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
   // assigment
   [[a = 5]];
+  [[a >>= 5]];
+  [[a *= 5]];
   // Variable DeclRefExpr
   a = [[b]];
   // label statement


Index: clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
===
--- clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
+++ clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
@@ -272,7 +272,7 @@
   // Extracting Exprs like a = 1 gives dummy = a = 1 which isn't useful.
   if (const BinaryOperator *BinOpExpr =
   dyn_cast_or_null(SelectedExpr)) {
-if (BinOpExpr->getOpcode() == BinaryOperatorKind::BO_Assign)
+if (BinOpExpr->isAssignmentOp())
   return false;
   }
   // For function and member function DeclRefs, we look for a parent that is a
Index: clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
@@ -371,6 +371,8 @@
   auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;}
   // assigment
   [[a = 5]];
+  [[a >>= 5]];
+  [[a *= 5]];
   // Variable DeclRefExpr
   a = [[b]];
   // label statement
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65337: [clangd] Disallow extraction of expression-statements.

2019-07-29 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added a comment.

What was the bug in getCallExpr() ?




Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:391
+return false;
+  Outer->dumpColor();
+  // Blacklist the most common places where an expr can appear but be unused.

Remove dump.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:445
+
+  // FIXME: ban extracting the RHS of an assignment: `a = [[foo()]]`
   return true;

Check if parent is an assignment binaryoperator or a vardecl?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:461
+  // For function and member function DeclRefs, extract the whole call.
+  if (const DeclRefExpr *DeclRef = dyn_cast_or_null(SelectedExpr))
 TargetNode = getCallExpr(N);

Can we combine both these IFs and remove the unused assignment?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65337



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


[PATCH] D65337: [clangd] Disallow extraction of expression-statements.

2019-07-29 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:329
   while(a < [[1]])
-[[a++]];
+a++;
   // do while

Change to a=[[1]];?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65337



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


[PATCH] D65486: [clangd] Ignore semicolons, whitespace, and comments in SelectionTree.

2019-07-31 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/Selection.cpp:50
+  S.StartOffset = SM.getFileOffset(Tok.location());
+  S.EndOffset = S.StartOffset + Tok.length();
+  if (S.StartOffset >= SelBegin && S.EndOffset <= SelEnd)

Would this work correctly for nested templates? Or do we need to use the 
specialized token length function that we use for toHalfOpenFileRange?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65486



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


[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-07-31 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: kadircet, sammccall.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov, mgorny.
Herald added a project: clang.

- Prototype version; Only looking for a high level review.
- Only works for extraction from free functions
- Basic analysis of the code being extracted.
- Extracts to a void function with no parameters.
- Doesn't handle semicolons yet.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp

Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,285 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using Node = SelectionTree::Node;
+using std::shared_ptr;
+
+class ExtractionTarget {
+public:
+  ExtractionTarget(const Node *N, const SourceManager &SM,
+   const ASTContext &Ctx);
+
+  // Check if the location is part of the TargetContext and before Target.
+  bool isInPreTarget(SourceLocation Loc) const {
+return !isOutsideTargetContext(Loc) && Loc < TargetRng.getBegin();
+  }
+
+  // Checks whether the Location is within the Target.
+  bool isInTarget(SourceLocation Loc) const {
+return SM.isPointWithin(Loc, TargetRng.getBegin(), TargetRng.getEnd());
+  }
+
+  // Check if the location is part of the TargetContext and after Target.
+  bool isInPostTarget(SourceLocation Loc) const {
+return !isOutsideTargetContext(Loc) && TargetRng.getEnd() < Loc;
+  }
+  // Check if the location is outside the TargetContext.
+  bool isOutsideTargetContext(SourceLocation Loc) const {
+return !SM.isPointWithin(Loc, TargetContextRng.getBegin(),
+ TargetContextRng.getEnd());
+  }
+  bool isExtractable() { return TargetRng.isValid() && TargetContext; }
+
+  tooling::Replacement replaceWithFuncCall(llvm::StringRef FuncName) const;
+  tooling::Replacement createFunctionDefinition(llvm::StringRef FuncName) const;
+  // The function inside which our target resides.
+  const FunctionDecl *TargetContext;
+
+private:
+  const Node *CommonAnc;
+  const SourceManager &SM;
+  const ASTContext &Ctx;
+  // The range of the code being extracted.
+  SourceRange TargetRng;
+  SourceRange TargetContextRng;
+
+  SourceRange computeTargetRange() const;
+};
+
+const FunctionDecl *computeTargetContext(const Node *CommonAnc) {
+  // Walk up the SelectionTree until we find a function Decl
+  for (const Node *CurNode = CommonAnc; CurNode; CurNode = CurNode->Parent) {
+if (const FunctionDecl *FD = CurNode->ASTNode.get()) {
+  // FIXME: Support extraction from methods.
+  if (CurNode->ASTNode.get())
+return nullptr;
+  return FD;
+}
+  }
+  return nullptr;
+}
+
+ExtractionTarget::ExtractionTarget(const Node *CommonAnc,
+   const SourceManager &SM,
+   const ASTContext &Ctx)
+: CommonAnc(CommonAnc), SM(SM), Ctx(Ctx) {
+  TargetRng = computeTargetRange();
+  if ((TargetContext = computeTargetContext(CommonAnc)))
+TargetContextRng =
+TargetContext->getSourceRange(); // TODO: Use toHalfOpenFileRange?
+}
+
+// TODO: Describe how this works
+SourceRange ExtractionTarget::computeTargetRange() const {
+  const LangOptions &LangOpts = Ctx.getLangOpts();
+  if (!CommonAnc)
+return SourceRange();
+  if (CommonAnc->Selected == SelectionTree::Selection::Complete)
+return *toHalfOpenFileRange(SM, LangOpts,
+CommonAnc->ASTNode.getSourceRange());
+  // FIXME: Bail out when it's partial selected. Wait for selectiontree
+  // semicolon fix.
+  if (CommonAnc->Selected == SelectionTree::Selection::Partial &&
+  !CommonAnc->ASTNode

[PATCH] D65574: Added hack to prevent toHalfOpenFileRange assertion fail

2019-08-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, ilya-biryukov.
Herald added a project: clang.

- Still need to investigate why this is happening.
- Fixes the crash described at https://github.com/clangd/clangd/issues/113


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65574

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/SourceCode.cpp


Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -311,8 +311,11 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
+// FIXME: Investigate when this assert fails. Added a hack until then.
+// assert(!FileRange.getEnd().isFileID() &&
+//   "Both Begin and End should be MacroIDs.");
+if(FileRange.getEnd().isFileID())
+  return SourceRange();
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
   FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
   FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
Index: clang-tools-extra/clangd/Selection.cpp
===
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -369,7 +369,8 @@
 //   }
 // Selecting "++x" or "x" will do the right thing.
 auto Range = toHalfOpenFileRange(SM, LangOpts, S);
-assert(Range && "We should be able to get the File Range");
+if(!Range)
+  return SelectionTree::Unselected;
 dlog("{1}claimRange: {0}", Range->printToString(SM), indent());
 auto B = SM.getDecomposedLoc(Range->getBegin());
 auto E = SM.getDecomposedLoc(Range->getEnd());


Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -311,8 +311,11 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
+// FIXME: Investigate when this assert fails. Added a hack until then.
+// assert(!FileRange.getEnd().isFileID() &&
+//   "Both Begin and End should be MacroIDs.");
+if(FileRange.getEnd().isFileID())
+  return SourceRange();
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
   FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
   FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
Index: clang-tools-extra/clangd/Selection.cpp
===
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -369,7 +369,8 @@
 //   }
 // Selecting "++x" or "x" will do the right thing.
 auto Range = toHalfOpenFileRange(SM, LangOpts, S);
-assert(Range && "We should be able to get the File Range");
+if(!Range)
+  return SelectionTree::Unselected;
 dlog("{1}claimRange: {0}", Range->printToString(SM), indent());
 auto B = SM.getDecomposedLoc(Range->getBegin());
 auto E = SM.getDecomposedLoc(Range->getEnd());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65574: Added hack to prevent toHalfOpenFileRange assertion fail

2019-08-02 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked an inline comment as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/SourceCode.cpp:314
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
+// FIXME: Investigate when this assert fails. Added a hack until then.
+// assert(!FileRange.getEnd().isFileID() &&

sammccall wrote:
> We have a reproducer, why can't we investigate now?
Doing that. Just wanted to stop the crashes in the meanwhile.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65574



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


[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-02 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked 2 inline comments as done.
SureYeaah added a comment.

In D65526#1612117 , @sammccall wrote:

> I guess you're looking for design review at this point.
>
> But the most important part of that is the documentation of the high-level 
> structure, which is entirely missing. I can't really infer it from the code 
> because most of the design is (presumably) not implemented at this point :-)


Aaah. Yes. Sorry. Makes sense.




Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp:110
+  // FIXME: Bail out when it's partial selected. Wait for selectiontree
+  // semicolon fix.
+  if (CommonAnc->Selected == SelectionTree::Selection::Partial &&

sammccall wrote:
> what is the fix you're waiting for?
The semicolon fix that has already landed now.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp:211
+  // Note that DRELocType is never OUTSIDECONTEXT.
+  if (DeclLocType + 1 != DRELocType)
+return;

sammccall wrote:
> this line seems very suspect, what are you trying to do and why?
> 
This just checks whether (DeclLocType, DRELocType) is either (PRETARGET, 
TARGET) or (TARGET, POSTTARGET). Could explicitly write it if needed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526



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


[PATCH] D65754: Fix toHalfOpenFileRange assertion fail

2019-08-05 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, ilya-biryukov.
Herald added a project: clang.

- Removed assumption that begin and end need to be in same file id.
- Fixes the crash at https://github.com/clangd/clangd/issues/113


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65754

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -295,37 +295,63 @@
   return SourceRange(std::min(R1.getBegin(), R2.getBegin()),
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
-
-// Returns the tokenFileRange for a given Location as a Token Range
+// If Loc is a macro arg expansion, return the immediate spelling loc.
+// Otherwise 
+// Assumes Loc is in a macro file ID
+static SourceRange getExpansionOrSpellingRange(SourceLocation Loc,
+   const SourceManager &SM,
+   const LangOptions &LangOpts) {
+  if (SM.isMacroArgExpansion(Loc))
+return SM.getImmediateSpellingLoc(Loc);
+  return toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+}
+
+// Returns the tokenFileRange for a given Range as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+// template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
-static SourceRange getTokenFileRange(SourceLocation Loc,
- const SourceManager &SM,
+static SourceRange getTokenFileRange(SourceRange Rng, const SourceManager &SM,
  const LangOptions &LangOpts) {
-  SourceRange FileRange = Loc;
-  while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
-if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
-} else {
-  SourceRange ExpansionRangeForBegin = toTokenRange(
-  SM.getImmediateExpansionRange(FileRange.getBegin()), SM, LangOpts);
-  SourceRange ExpansionRangeForEnd = toTokenRange(
-  SM.getImmediateExpansionRange(FileRange.getEnd()), SM, LangOpts);
-  FileRange = unionTokenRange(ExpansionRangeForBegin, ExpansionRangeForEnd,
-  SM, LangOpts);
-}
+  // Map from FileID hash to SourceRange
+  std::map RngMap;
+  // Adds a Location to the RngMap
+  auto AddLocToMap = [&RngMap, &SM, &LangOpts](SourceLocation Loc) {
+unsigned FileIDHash = SM.getFileID(Loc).getHashValue();
+auto It = RngMap.find(FileIDHash);
+if (It == RngMap.end())
+  RngMap[FileIDHash] = Loc;
+else
+  It->second = unionTokenRange(It->second, Loc, SM, LangOpts);
+  };
+  auto AddRngToMap = [&](SourceRange SR) {
+AddLocToMap(SR.getBegin());
+AddLocToMap(SR.getEnd());
+  };
+  // Initialize RngMap
+  AddRngToMap(Rng);
+  // Iterate until only one range is left which is not a macroID
+  for (auto It = RngMap.rbegin();
+   !RngMap.empty() && It->second.getBegin().isMacroID();
+   It = RngMap.

[PATCH] D65754: Fix toHalfOpenFileRange assertion fail

2019-08-06 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213583.
SureYeaah added a comment.

Implemented function to get expansion range such that ends are both in the same 
file id.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65754

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -296,14 +296,57 @@
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
 
-// Returns the tokenFileRange for a given Location as a Token Range
+// Check if two locations have the same file id.
+static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2,
+   const SourceManager &SM) {
+  return SM.getFileID(Loc1) == SM.getFileID(Loc2);
+}
+
+// Find an expansion range (not necessarily immediate) the ends of which are in
+// the same file id.
+static SourceRange getExpansionRangeInSameFiles(SourceLocation Loc,
+const SourceManager &SM,
+const LangOptions &LangOpts) {
+  SourceRange ExpansionRange =
+  toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+  // Fast path for most common cases.
+  if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM))
+return ExpansionRange;
+  // Expand begin of Expansion range till the top and map with file id hash.
+  llvm::DenseMap BeginExpansions;
+  SourceRange BeginExpansion = ExpansionRange.getBegin();
+  while (1) {
+BeginExpansions[SM.getFileID(BeginExpansion.getBegin()).getHashValue()] =
+BeginExpansion;
+if (BeginExpansion.getBegin().isFileID())
+  break;
+BeginExpansion = toTokenRange(
+SM.getImmediateExpansionRange(BeginExpansion.getBegin()), SM, LangOpts);
+  }
+  // Expand the end of Expansion range till the top and find the first match in
+  // BeginExpansions.
+  SourceRange EndExpansion = ExpansionRange.getEnd();
+  while (1) {
+auto It = BeginExpansions.find(
+SM.getFileID(EndExpansion.getEnd()).getHashValue());
+if (It != BeginExpansions.end())
+  return unionTokenRange(It->second, EndExpansion, SM, LangOpts);
+if (EndExpansion.getEnd().isFileID())
+  break;
+EndExpansion = toTokenRange(
+SM.getImmediateExpansionRange(EndExpansion.getEnd()), SM, LangOpts);
+  }
+  llvm_unreachable(
+  "We should able to find a common ancestor in the expansion tree.");
+}
+// Returns the file range for a given Location as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+//   template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
 static SourceRange getTokenFileRange(SourceLocation Loc,
@@ -311,16 +354,20 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
+  FileRange = unionTokenRange(
+  SM.getImmediateSpellin

[PATCH] D65804: Fixed toHalfOpenFileRange assertion fail

2019-08-06 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, 
ilya-biryukov.
Herald added a project: clang.

- Added new function that gets Expansion range with both ends in the

same file.

- Fixes the crash at https://github.com/clangd/clangd/issues/113


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65804

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -296,14 +296,52 @@
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
 
-// Returns the tokenFileRange for a given Location as a Token Range
+// Check if two locations have the same file id.
+static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2,
+   const SourceManager &SM) {
+  return SM.getFileID(Loc1) == SM.getFileID(Loc2);
+}
+
+// Find an expansion range (not necessarily immediate) the ends of which are in
+// the same file id.
+static SourceRange
+getExpansionTokenRangeInSameFile(SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+  SourceRange ExpansionRange =
+  toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+  // Fast path for most common cases.
+  if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM))
+return ExpansionRange;
+  // Record the stack of expansion locations for the beginning, keyed by FileID.
+  llvm::DenseMap BeginExpansions;
+  for (SourceLocation Begin = ExpansionRange.getBegin(); Begin.isValid();
+   Begin = Begin.isFileID()
+   ? SourceLocation()
+   : SM.getImmediateExpansionRange(Begin).getBegin()) {
+BeginExpansions[SM.getFileID(Begin).getHashValue()] = Begin;
+  }
+  // Move up the stack of expansion locations for the end until we find the
+  // location in BeginExpansions with that has the same file id.
+  for (SourceLocation End = ExpansionRange.getEnd(); End.isValid();
+   End = End.isFileID() ? SourceLocation()
+: toTokenRange(SM.getImmediateExpansionRange(End),
+   SM, LangOpts)
+  .getEnd()) {
+auto It = BeginExpansions.find(SM.getFileID(End).getHashValue());
+if (It != BeginExpansions.end())
+  return {It->second, End};
+  }
+  llvm_unreachable(
+  "We should able to find a common ancestor in the expansion tree.");
+}
+// Returns the file range for a given Location as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+//   template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
 static SourceRange getTokenFileRange(SourceLocation Loc,
@@ -311,16 +349,19 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
+  FileRange = unionTokenRange(
+  SM.getImmediateSpellingLoc(FileRange.getBegin()

[PATCH] D65754: Fix toHalfOpenFileRange assertion fail

2019-08-06 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213599.
SureYeaah marked 8 inline comments as done.
SureYeaah added a comment.

Addressed review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65754

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -296,14 +296,52 @@
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
 
-// Returns the tokenFileRange for a given Location as a Token Range
+// Check if two locations have the same file id.
+static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2,
+   const SourceManager &SM) {
+  return SM.getFileID(Loc1) == SM.getFileID(Loc2);
+}
+
+// Find an expansion range (not necessarily immediate) the ends of which are in
+// the same file id.
+static SourceRange
+getExpansionTokenRangeInSameFile(SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+  SourceRange ExpansionRange =
+  toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+  // Fast path for most common cases.
+  if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM))
+return ExpansionRange;
+  // Record the stack of expansion locations for the beginning, keyed by FileID.
+  llvm::DenseMap BeginExpansions;
+  for (SourceLocation Begin = ExpansionRange.getBegin(); Begin.isValid();
+   Begin = Begin.isFileID()
+   ? SourceLocation()
+   : SM.getImmediateExpansionRange(Begin).getBegin()) {
+BeginExpansions[SM.getFileID(Begin).getHashValue()] = Begin;
+  }
+  // Move up the stack of expansion locations for the end until we find the
+  // location in BeginExpansions with that has the same file id.
+  for (SourceLocation End = ExpansionRange.getEnd(); End.isValid();
+   End = End.isFileID() ? SourceLocation()
+: toTokenRange(SM.getImmediateExpansionRange(End),
+   SM, LangOpts)
+  .getEnd()) {
+auto It = BeginExpansions.find(SM.getFileID(End).getHashValue());
+if (It != BeginExpansions.end())
+  return {It->second, End};
+  }
+  llvm_unreachable(
+  "We should able to find a common ancestor in the expansion tree.");
+}
+// Returns the file range for a given Location as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+//   template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
 static SourceRange getTokenFileRange(SourceLocation Loc,
@@ -311,16 +349,19 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
+  FileRange = unionTokenRange(
+  SM.getImmediateSpellingLoc(FileRange.getBegin()),
+  SM.getImmediateSpellingLoc(FileRange.getEnd()), SM, LangOpts);
+  

[PATCH] D65754: Fix toHalfOpenFileRange assertion fail

2019-08-06 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213614.
SureYeaah added a comment.

use fileID instead of hash in map


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65754

Files:
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/unittests/SourceCodeTests.cpp

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -296,14 +296,52 @@
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
 
-// Returns the tokenFileRange for a given Location as a Token Range
+// Check if two locations have the same file id.
+static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2,
+   const SourceManager &SM) {
+  return SM.getFileID(Loc1) == SM.getFileID(Loc2);
+}
+
+// Find an expansion range (not necessarily immediate) the ends of which are in
+// the same file id.
+static SourceRange
+getExpansionTokenRangeInSameFile(SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+  SourceRange ExpansionRange =
+  toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+  // Fast path for most common cases.
+  if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM))
+return ExpansionRange;
+  // Record the stack of expansion locations for the beginning, keyed by FileID.
+  llvm::DenseMap BeginExpansions;
+  for (SourceLocation Begin = ExpansionRange.getBegin(); Begin.isValid();
+   Begin = Begin.isFileID()
+   ? SourceLocation()
+   : SM.getImmediateExpansionRange(Begin).getBegin()) {
+BeginExpansions[SM.getFileID(Begin)] = Begin;
+  }
+  // Move up the stack of expansion locations for the end until we find the
+  // location in BeginExpansions with that has the same file id.
+  for (SourceLocation End = ExpansionRange.getEnd(); End.isValid();
+   End = End.isFileID() ? SourceLocation()
+: toTokenRange(SM.getImmediateExpansionRange(End),
+   SM, LangOpts)
+  .getEnd()) {
+auto It = BeginExpansions.find(SM.getFileID(End));
+if (It != BeginExpansions.end())
+  return {It->second, End};
+  }
+  llvm_unreachable(
+  "We should able to find a common ancestor in the expansion tree.");
+}
+// Returns the file range for a given Location as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+//   template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
 static SourceRange getTokenFileRange(SourceLocation Loc,
@@ -311,16 +349,19 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd()));
+  FileRange = unionTokenRange(
+  SM.getImmediateSpellingLoc(FileRange.getBegin()),
+  SM.getImmediateSpellingLoc(FileRange.getEnd()), SM, LangOpts);
+  assert(inSameFile(FileRange.getBegin(), FileRange.getEnd(), SM));

[PATCH] D65754: Fix toHalfOpenFileRange assertion fail

2019-08-06 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368058: Fixed toHalfOpenFileRange assertion fail (authored 
by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65754?vs=213614&id=213645#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D65754

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

Index: clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SourceCodeTests.cpp
@@ -460,15 +460,22 @@
 #define FOO(X, Y) int Y = ++X
 #define BAR(X) X + 1
 #define ECHO(X) X
+
+#define BUZZ BAZZ(ADD)
+#define BAZZ(m) m(1)
+#define ADD(a) int f = a + 1;
 template
 class P {};
-void f() {
+
+int main() {
   $a[[P a]];
   $b[[int b = 1]];
   $c[[FOO(b, c)]]; 
   $d[[FOO(BAR(BAR(b)), d)]];
   // FIXME: We might want to select everything inside the outer ECHO.
   ECHO(ECHO($e[[int) ECHO(e]]));
+  // Shouldn't crash.
+  $f[[BUZZ]];
 }
   )cpp");
 
@@ -495,6 +502,7 @@
   CheckRange("c");
   CheckRange("d");
   CheckRange("e");
+  CheckRange("f");
 }
 
 } // namespace
Index: clang-tools-extra/trunk/clangd/SourceCode.cpp
===
--- clang-tools-extra/trunk/clangd/SourceCode.cpp
+++ clang-tools-extra/trunk/clangd/SourceCode.cpp
@@ -296,14 +296,52 @@
  E1 < E2 ? R2.getEnd() : R1.getEnd());
 }
 
-// Returns the tokenFileRange for a given Location as a Token Range
+// Check if two locations have the same file id.
+static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2,
+   const SourceManager &SM) {
+  return SM.getFileID(Loc1) == SM.getFileID(Loc2);
+}
+
+// Find an expansion range (not necessarily immediate) the ends of which are in
+// the same file id.
+static SourceRange
+getExpansionTokenRangeInSameFile(SourceLocation Loc, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+  SourceRange ExpansionRange =
+  toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts);
+  // Fast path for most common cases.
+  if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM))
+return ExpansionRange;
+  // Record the stack of expansion locations for the beginning, keyed by FileID.
+  llvm::DenseMap BeginExpansions;
+  for (SourceLocation Begin = ExpansionRange.getBegin(); Begin.isValid();
+   Begin = Begin.isFileID()
+   ? SourceLocation()
+   : SM.getImmediateExpansionRange(Begin).getBegin()) {
+BeginExpansions[SM.getFileID(Begin)] = Begin;
+  }
+  // Move up the stack of expansion locations for the end until we find the
+  // location in BeginExpansions with that has the same file id.
+  for (SourceLocation End = ExpansionRange.getEnd(); End.isValid();
+   End = End.isFileID() ? SourceLocation()
+: toTokenRange(SM.getImmediateExpansionRange(End),
+   SM, LangOpts)
+  .getEnd()) {
+auto It = BeginExpansions.find(SM.getFileID(End));
+if (It != BeginExpansions.end())
+  return {It->second, End};
+  }
+  llvm_unreachable(
+  "We should able to find a common ancestor in the expansion tree.");
+}
+// Returns the file range for a given Location as a Token Range
 // This is quite similar to getFileLoc in SourceManager as both use
 // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs).
 // However:
 // - We want to maintain the full range information as we move from one file to
 //   the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange.
-// - We want to split '>>' tokens as the lexer parses the '>>' in template
-//   instantiations as a '>>' instead of a '>'.
+// - We want to split '>>' tokens as the lexer parses the '>>' in nested
+//   template instantiations as a '>>' instead of two '>'s.
 // There is also getExpansionRange but it simply calls
 // getImmediateExpansionRange on the begin and ends separately which is wrong.
 static SourceRange getTokenFileRange(SourceLocation Loc,
@@ -311,16 +349,19 @@
  const LangOptions &LangOpts) {
   SourceRange FileRange = Loc;
   while (!FileRange.getBegin().isFileID()) {
-assert(!FileRange.getEnd().isFileID() &&
-   "Both Begin and End should be MacroIDs.");
 if (SM.isMacroArgExpansion(FileRange.getBegin())) {
-  FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin()));
-  FileRange.setEnd(SM.getImmediateSpellingLoc(FileRan

[PATCH] D65878: [Refactor] Moving SourceExtraction header from lib to include

2019-08-07 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added a reviewer: arphaman.
Herald added subscribers: cfe-commits, kadircet, dexonsmith, ilya-biryukov.
Herald added a project: clang.

- Moved the SourceExtraction header from lib to include so that it can

be used in clangd.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65878

Files:
  clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
  clang/lib/Tooling/Refactoring/Extract/Extract.cpp
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -6,7 +6,7 @@
 //
 
//===--===//
 
-#include "SourceExtraction.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
Index: clang/lib/Tooling/Refactoring/Extract/Extract.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -13,12 +13,12 @@
 
//===--===//
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
-#include "SourceExtraction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 
 namespace clang {
 namespace tooling {
Index: clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
+++ clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -6,8 +6,8 @@
 //
 
//===--===//
 
-#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
 
 #include "clang/Basic/LLVM.h"
 


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -6,7 +6,7 @@
 //
 //===--===//
 
-#include "SourceExtraction.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
Index: clang/lib/Tooling/Refactoring/Extract/Extract.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -13,12 +13,12 @@
 //===--===//
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
-#include "SourceExtraction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 
 namespace clang {
 namespace tooling {
Index: clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
+++ clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -6,8 +6,8 @@
 //
 //===--===//
 
-#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
 
 #include "clang/Basic/LLVM.h"
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65883: [Extract] Fixed SemicolonExtractionPolicy for Do and Switch Stmt

2019-08-07 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: arphaman, sammccall.
Herald added subscribers: cfe-commits, dexonsmith.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65883

Files:
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -36,12 +36,17 @@
 return isSemicolonRequiredAfter(While->getBody());
   if (const auto *For = dyn_cast(S))
 return isSemicolonRequiredAfter(For->getBody());
+  if (const auto *Do = dyn_cast(S))
+return isSemicolonRequiredAfter(Do->getBody());
   if (const auto *CXXFor = dyn_cast(S))
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -36,12 +36,17 @@
 return isSemicolonRequiredAfter(While->getBody());
   if (const auto *For = dyn_cast(S))
 return isSemicolonRequiredAfter(For->getBody());
+  if (const auto *Do = dyn_cast(S))
+return isSemicolonRequiredAfter(Do->getBody());
   if (const auto *CXXFor = dyn_cast(S))
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65883: [Extract] Fixed SemicolonExtractionPolicy for SwitchStmt and SwitchCase

2019-08-07 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213909.
SureYeaah added a comment.

Removed Do


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65883

Files:
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65883: [Extract] Fixed SemicolonExtractionPolicy for SwitchStmt and SwitchCase

2019-08-07 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213925.
SureYeaah added a comment.

Added tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65883

Files:
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
  clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp


Index: clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
===
--- clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
+++ clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
@@ -64,6 +64,7 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: }
 
+
 void extractStatementNotSemiWhile() {
   /*range eextract=->+2:4*/while (true) {
 int x = 0;
@@ -190,3 +191,15 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: //
 // CHECK-NEXT: }
+
+void careForSwitchSemicolon() {
+  /*range mextract=->+0:51*/switch(0) default: break;
+}
+// CHECK: 1 'mextract' results:
+// CHECK:  static void extracted() {
+// CHECK-NEXT: switch(0) default: break;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: void careForSwitchSemicolon() {
+// CHECK-NEXT: extracted();{{$}}
+// CHECK-NEXT: }
+
Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:


Index: clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
===
--- clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
+++ clang/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
@@ -64,6 +64,7 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: }
 
+
 void extractStatementNotSemiWhile() {
   /*range eextract=->+2:4*/while (true) {
 int x = 0;
@@ -190,3 +191,15 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: //
 // CHECK-NEXT: }
+
+void careForSwitchSemicolon() {
+  /*range mextract=->+0:51*/switch(0) default: break;
+}
+// CHECK: 1 'mextract' results:
+// CHECK:  static void extracted() {
+// CHECK-NEXT: switch(0) default: break;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: void careForSwitchSemicolon() {
+// CHECK-NEXT: extracted();{{$}}
+// CHECK-NEXT: }
+
Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65878: [Refactor] Moving SourceExtraction header from lib to include

2019-08-07 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 213973.
SureYeaah added a comment.

Added endif comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65878

Files:
  clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
  clang/lib/Tooling/Refactoring/Extract/Extract.cpp
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
  clang/lib/Tooling/Refactoring/Extract/SourceExtraction.h


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -6,7 +6,7 @@
 //
 
//===--===//
 
-#include "SourceExtraction.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
Index: clang/lib/Tooling/Refactoring/Extract/Extract.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -13,12 +13,12 @@
 
//===--===//
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
-#include "SourceExtraction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 
 namespace clang {
 namespace tooling {
Index: clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
+++ clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -6,8 +6,8 @@
 //
 
//===--===//
 
-#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
 
 #include "clang/Basic/LLVM.h"
 
@@ -48,4 +48,4 @@
 } // end namespace tooling
 } // end namespace clang
 
-#endif // LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#endif //LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H


Index: clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ clang/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -6,7 +6,7 @@
 //
 //===--===//
 
-#include "SourceExtraction.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
Index: clang/lib/Tooling/Refactoring/Extract/Extract.cpp
===
--- clang/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ clang/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -13,12 +13,12 @@
 //===--===//
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
-#include "SourceExtraction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 
 namespace clang {
 namespace tooling {
Index: clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
+++ clang/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -6,8 +6,8 @@
 //
 //===--===//
 
-#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
 
 #include "clang/Basic/LLVM.h"
 
@@ -48,4 +48,4 @@
 } // end namespace tooling
 } // end namespace clang
 
-#endif // LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#endif //LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-comm

[PATCH] D65883: [Extract] Fixed SemicolonExtractionPolicy for SwitchStmt and SwitchCase

2019-08-08 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368267: [Extract] Fixed SemicolonExtractionPolicy for 
SwitchStmt and SwitchCase (authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65883?vs=213925&id=214084#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D65883

Files:
  cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
  cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp


Index: cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
===
--- cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
+++ cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
@@ -64,6 +64,7 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: }
 
+
 void extractStatementNotSemiWhile() {
   /*range eextract=->+2:4*/while (true) {
 int x = 0;
@@ -190,3 +191,15 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: //
 // CHECK-NEXT: }
+
+void careForSwitchSemicolon() {
+  /*range mextract=->+0:51*/switch(0) default: break;
+}
+// CHECK: 1 'mextract' results:
+// CHECK:  static void extracted() {
+// CHECK-NEXT: switch(0) default: break;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: void careForSwitchSemicolon() {
+// CHECK-NEXT: extracted();{{$}}
+// CHECK-NEXT: }
+
Index: cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:


Index: cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
===
--- cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
+++ cfe/trunk/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp
@@ -64,6 +64,7 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: }
 
+
 void extractStatementNotSemiWhile() {
   /*range eextract=->+2:4*/while (true) {
 int x = 0;
@@ -190,3 +191,15 @@
 // CHECK-NEXT: extracted();{{$}}
 // CHECK-NEXT: //
 // CHECK-NEXT: }
+
+void careForSwitchSemicolon() {
+  /*range mextract=->+0:51*/switch(0) default: break;
+}
+// CHECK: 1 'mextract' results:
+// CHECK:  static void extracted() {
+// CHECK-NEXT: switch(0) default: break;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: void careForSwitchSemicolon() {
+// CHECK-NEXT: extracted();{{$}}
+// CHECK-NEXT: }
+
Index: cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -40,8 +40,11 @@
 return isSemicolonRequiredAfter(CXXFor->getBody());
   if (const auto *ObjCFor = dyn_cast(S))
 return isSemicolonRequiredAfter(ObjCFor->getBody());
+  if(const auto *Switch = dyn_cast(S))
+return isSemicolonRequiredAfter(Switch->getBody());
+  if(const auto *Case = dyn_cast(S))
+return isSemicolonRequiredAfter(Case->getSubStmt());
   switch (S->getStmtClass()) {
-  case Stmt::SwitchStmtClass:
   case Stmt::CXXTryStmtClass:
   case Stmt::ObjCAtSynchronizedStmtClass:
   case Stmt::ObjCAutoreleasePoolStmtClass:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65878: [Refactor] Moving SourceExtraction header from lib to include

2019-08-13 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368743: [Refactor] Moving SourceExtraction header from lib 
to include (authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65878?vs=213973&id=214907#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D65878

Files:
  cfe/trunk/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
  cfe/trunk/lib/Tooling/Refactoring/Extract/Extract.cpp
  cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
  cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.h

Index: cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
===
--- cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
+++ cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp
@@ -6,7 +6,7 @@
 //
 //===--===//
 
-#include "SourceExtraction.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
Index: cfe/trunk/lib/Tooling/Refactoring/Extract/Extract.cpp
===
--- cfe/trunk/lib/Tooling/Refactoring/Extract/Extract.cpp
+++ cfe/trunk/lib/Tooling/Refactoring/Extract/Extract.cpp
@@ -13,12 +13,12 @@
 //===--===//
 
 #include "clang/Tooling/Refactoring/Extract/Extract.h"
-#include "SourceExtraction.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
 
 namespace clang {
 namespace tooling {
Index: cfe/trunk/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- cfe/trunk/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
+++ cfe/trunk/include/clang/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -0,0 +1,51 @@
+//===--- SourceExtraction.cpp - Clang refactoring library -===//
+//
+// 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+#define LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
+
+#include "clang/Basic/LLVM.h"
+
+namespace clang {
+
+class LangOptions;
+class SourceManager;
+class SourceRange;
+class Stmt;
+
+namespace tooling {
+
+/// Determines which semicolons should be inserted during extraction.
+class ExtractionSemicolonPolicy {
+public:
+  bool isNeededInExtractedFunction() const {
+return IsNeededInExtractedFunction;
+  }
+
+  bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; }
+
+  /// Returns the semicolon insertion policy that is needed for extraction of
+  /// the given statement from the given source range.
+  static ExtractionSemicolonPolicy compute(const Stmt *S,
+   SourceRange &ExtractedRange,
+   const SourceManager &SM,
+   const LangOptions &LangOpts);
+
+private:
+  ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction,
+bool IsNeededInOriginalFunction)
+  : IsNeededInExtractedFunction(IsNeededInExtractedFunction),
+IsNeededInOriginalFunction(IsNeededInOriginalFunction) {}
+  bool IsNeededInExtractedFunction;
+  bool IsNeededInOriginalFunction;
+};
+
+} // end namespace tooling
+} // end namespace clang
+
+#endif //LLVM_CLANG_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
Index: cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.h
===
--- cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.h
+++ cfe/trunk/lib/Tooling/Refactoring/Extract/SourceExtraction.h
@@ -1,51 +0,0 @@
-//===--- SourceExtraction.cpp - Clang refactoring library -===//
-//
-// 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
-//
-//===--===//
-
-#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H
-
-#in

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-14 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215077.
SureYeaah marked 11 inline comments as done.
SureYeaah added a comment.

Refactored design and added unit tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
  clang-tools-extra/clangd/unittests/TweakTesting.h
  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
@@ -133,7 +133,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;
@@ -164,7 +165,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";
@@ -345,11 +346,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;
@@ -360,13 +361,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)
@@ -462,8 +463,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;
@@ -491,26 +492,27 @@
   checkAvailable(ID, "^vo^id^ ^f(^) {^}^"); // available everywhere.
   checkAvailable(ID, "[[int a; int b;]]");
   const char *Input = "void ^f() {}";
-  const char *Output = "/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f() {}";
+  const char *Output = "/* storage.type.primitive.cpp */void /* "
+   "entity.name.function.cpp */f() {}";
   checkTransform(ID, Input, Output);
 
   checkTransform(ID,
-  R"cpp(
+ R"cpp(
 [[void f1();
 void f2();]]
 )cpp",
-  R"cpp(
+ R"cpp(
 /* storage.type.primitive.cpp */void /* entity.name.function.cpp */f1();
 /* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2();
 )cpp");
 
-   checkTransform(ID,
-  R"cpp(
+  checkTransform(ID,
+ R"cpp(
 void f1();
 void f2() {^};
 )cpp",
 
-  R"cpp(
+ R"cpp(
 void f1();
 /* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2() {};
 )cpp");
@@ -590,7 +592,7 @@
   StartsWith("fail: Could not expand type of lambda expression"));
   // inline 

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-14 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215089.
SureYeaah added a comment.

Removed unrelated changes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -599,6 +599,93 @@
 R"cpp(const char * x = "test")cpp");
 }
 
+TWEAK_TEST(ExtractFunction);
+TEST_F(ExtractFunctionTest, PrepareFunctionTest) {
+  Header = R"cpp(
+#define F(BODY) void FFF() { BODY }
+  )cpp";
+  Context = Function;
+  EXPECT_AVAILABLE(R"cpp(
+[[int sum = 0;
+for(;;)
+  sum++;]]
+for(int i = 0; i < 5; i++) {
+  sum += i;
+}
+  )cpp");
+  EXPECT_AVAILABLE(R"cpp([[int x;]])cpp");
+  // TODO: Add tests for macros after selectionTree works properly for macros.
+  // EXPECT_AVAILABLE(R"cpp( F (int x = 0; [[x = 1;]])cpp");
+  // FIXME: This should be unavailable since partially selected but
+  // selectionTree doesn't always work correctly for VarDecls.
+  //EXPECT_UNAVAILABLE(R"cpp(int [[x = 0]];)cpp");
+  EXPECT_UNAVAILABLE(R"cpp(
+int sum = 0;
+for(;;)
+  [[sum++;
+sum++;]]
+  )cpp");
+  // Expressions aren't extracted.
+  EXPECT_UNAVAILABLE(R"cpp(int x = 0; [[x++;]])cpp");
+  // FIXME: ExtractFunction should be unavailable inside loop construct
+  // initalizer/condition.
+  // EXPECT_UNAVAILABLE(R"cpp( for([[int i = 0; i < 5;]] i++) )cpp");
+}
+
+TEST_F(ExtractFunctionTest, PrepareMethodTest) {
+  EXPECT_UNAVAILABLE(R"cpp(
+class T {
+  void f() {
+[[int x;]]
+  }
+};
+  )cpp");
+}
+
+TEST_F(ExtractFunctionTest, ApplyTest) {
+  // We can extract from templated functions as long as no reference in the
+  // extraction depends on the template.
+  // Checks const qualifier and extraction parameters.
+  Header = R"cpp(
+  )cpp";
+  EXPECT_EQ(apply(
+R"cpp(
+struct FOO {
+  int x;
+};
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  [[a += foo.x; b = c;]]
+})cpp"),
+R"cpp(
+struct FOO {
+  int x;
+};
+void extracted(int &a, int &b, const int &c, struct FOO &foo) {a += foo.x; b = c;}
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  extracted(a, b, c, foo);
+})cpp");
+  auto ShouldFail = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), StartsWith("fail:"));
+  };
+  // Don't extract because needs hoisting.
+  ShouldFail(R"cpp( void f() { [[int a = 5;]] a++;})cpp");
+  // Don't extract parameters that depend on template.
+  ShouldFail(R"cpp( template void f() { [[int a = N;]] })cpp");
+  ShouldFail(R"cpp( template void f() { [[T t;]] })cpp");
+  // Don't extract return
+  ShouldFail(R"cpp( int f() { int a = 5; [[return a;]]})cpp");
+  // Don't extract break and continue.
+  // FIXME: We should be able to extract this.
+  ShouldFail(R"cpp( int f() { [[for(;;) break;]]})cpp");
+  ShouldFail(R"cpp( int f() { for(;;) [[continue;]]})cpp");
+  // Don't extract when we need to make a function as a parameter.
+  ShouldFail(R"cpp( void f() { [[int a; f();]] } )cpp");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,536 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+using Node = SelectionTree::Node;
+
+// Source is the part of code th

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-14 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215098.
SureYeaah added a comment.

Removed debug info


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -599,6 +599,97 @@
 R"cpp(const char * x = "test")cpp");
 }
 
+TWEAK_TEST(ExtractFunction);
+TEST_F(ExtractFunctionTest, PrepareFunctionTest) {
+  Header = R"cpp(
+#define F(BODY) void FFF() { BODY }
+  )cpp";
+  Context = Function;
+  EXPECT_AVAILABLE(R"cpp(
+[[int sum = 0;
+for(;;)
+  sum++;]]
+for(int i = 0; i < 5; i++) {
+  sum += i;
+}
+  )cpp");
+  EXPECT_AVAILABLE(R"cpp([[int x;]])cpp");
+  // TODO: Add tests for macros after selectionTree works properly for macros.
+  // EXPECT_AVAILABLE(R"cpp( F (int x = 0; [[x = 1;]])cpp");
+  // FIXME: This should be unavailable since partially selected but
+  // selectionTree doesn't always work correctly for VarDecls.
+  //EXPECT_UNAVAILABLE(R"cpp(int [[x = 0]];)cpp");
+  EXPECT_UNAVAILABLE(R"cpp(
+int sum = 0;
+for(;;)
+  [[sum++;
+sum++;]]
+  )cpp");
+  // Expressions aren't extracted.
+  EXPECT_UNAVAILABLE(R"cpp(int x = 0; [[x++;]])cpp");
+  // FIXME: ExtractFunction should be unavailable inside loop construct
+  // initalizer/condition.
+  // EXPECT_UNAVAILABLE(R"cpp( for([[int i = 0; i < 5;]] i++) )cpp");
+}
+
+TEST_F(ExtractFunctionTest, PrepareMethodTest) {
+  EXPECT_UNAVAILABLE(R"cpp(
+class T {
+  void f() {
+[[int x;]]
+  }
+};
+  )cpp");
+}
+
+TEST_F(ExtractFunctionTest, ApplyTest) {
+  // We can extract from templated functions as long as no reference in the
+  // extraction depends on the template.
+  // Checks const qualifier and extraction parameters.
+  Header = R"cpp(
+  )cpp";
+  EXPECT_EQ(apply(
+R"cpp(
+struct FOO {
+  int x;
+};
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  [[a += foo.x; b = c; *ptr++;]]
+})cpp"),
+R"cpp(
+struct FOO {
+  int x;
+};
+void extracted(int &a, int &b, const int &c, struct FOO &foo, int * &ptr) {
+a += foo.x; b = c; *ptr++;
+}
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  extracted(a, b, c, foo, ptr);
+})cpp");
+  auto ShouldFail = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), StartsWith("fail:"));
+  };
+  // Don't extract because needs hoisting.
+  ShouldFail(R"cpp( void f() { [[int a = 5;]] a++;})cpp");
+  // Don't extract parameters that depend on template.
+  ShouldFail(R"cpp( template void f() { [[int a = N;]] })cpp");
+  ShouldFail(R"cpp( template void f() { [[T t;]] })cpp");
+  // Don't extract return
+  ShouldFail(R"cpp( int f() { int a = 5; [[return a;]]})cpp");
+  // Don't extract break and continue.
+  // FIXME: We should be able to extract this.
+  ShouldFail(R"cpp( int f() { [[for(;;) break;]]})cpp");
+  ShouldFail(R"cpp( int f() { for(;;) [[continue;]]})cpp");
+  // Don't extract when we need to make a function as a parameter.
+  ShouldFail(R"cpp( void f() { [[int a; f();]] } )cpp");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,534 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+namespace {
+
+usi

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-14 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215131.
SureYeaah added a comment.

Better Naming


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -599,6 +599,103 @@
 R"cpp(const char * x = "test")cpp");
 }
 
+TWEAK_TEST(ExtractFunction);
+TEST_F(ExtractFunctionTest, PrepareFunctionTest) {
+  Header = R"cpp(
+#define F(BODY) void FFF() { BODY }
+  )cpp";
+  Context = Function;
+  EXPECT_AVAILABLE(R"cpp(
+[[int sum = 0;
+for(;;)
+  sum++;]]
+for(int i = 0; i < 5; i++) {
+  sum += i;
+}
+  )cpp");
+  EXPECT_AVAILABLE(R"cpp([[int x;]])cpp");
+  // TODO: Add tests for macros after selectionTree works properly for macros.
+  // EXPECT_AVAILABLE(R"cpp( F (int x = 0; [[x = 1;]])cpp");
+  // FIXME: This should be unavailable since partially selected but
+  // selectionTree doesn't always work correctly for VarDecls.
+  //EXPECT_UNAVAILABLE(R"cpp(int [[x = 0]];)cpp");
+  EXPECT_UNAVAILABLE(R"cpp(
+int sum = 0;
+for(;;)
+  [[sum++;
+sum++;]]
+  )cpp");
+  // Expressions aren't extracted.
+  EXPECT_UNAVAILABLE(R"cpp(int x = 0; [[x++;]])cpp");
+  // FIXME: ExtractFunction should be unavailable inside loop construct
+  // initalizer/condition.
+  // EXPECT_UNAVAILABLE(R"cpp( for([[int i = 0; i < 5;]] i++) )cpp");
+}
+
+TEST_F(ExtractFunctionTest, PrepareMethodTest) {
+  EXPECT_UNAVAILABLE(R"cpp(
+class T {
+  void f() {
+[[int x;]]
+  }
+};
+  )cpp");
+}
+
+TEST_F(ExtractFunctionTest, ApplyTest) {
+  // We can extract from templated functions as long as no reference in the
+  // extraction depends on the template.
+  // Checks const qualifier and extraction parameters.
+  Header = R"cpp(
+  )cpp";
+  EXPECT_EQ(apply(
+R"cpp(
+struct FOO {
+  int x;
+};
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  [[a += foo.x;
+  b = c; 
+  *ptr++;
+  int d = 5 /* check if comment is extracted */ ;]]
+})cpp"),
+R"cpp(
+struct FOO {
+  int x;
+};
+void extracted(int &a, int &b, const int &c, struct FOO &foo, int * &ptr) {
+a += foo.x;
+  b = c; 
+  *ptr++;
+  int d = 5 /* check if comment is extracted */ ;
+}
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  extracted(a, b, c, foo, ptr);
+})cpp");
+  auto ShouldFail = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), StartsWith("fail:"));
+  };
+  // Don't extract because needs hoisting.
+  ShouldFail(R"cpp( void f() { [[int a = 5;]] a++;})cpp");
+  // Don't extract parameters that depend on template.
+  ShouldFail(R"cpp( template void f() { [[int a = N;]] })cpp");
+  ShouldFail(R"cpp( template void f() { [[T t;]] })cpp");
+  // Don't extract return
+  ShouldFail(R"cpp( int f() { int a = 5; [[return a;]]})cpp");
+  // Don't extract break and continue.
+  // FIXME: We should be able to extract this.
+  ShouldFail(R"cpp( int f() { [[for(;;) break;]]})cpp");
+  ShouldFail(R"cpp( int f() { for(;;) [[continue;]]})cpp");
+  // Don't extract when we need to make a function as a parameter.
+  ShouldFail(R"cpp( void f() { [[int a; f();]] } )cpp");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,534 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "clang/Tooling/Refactoring/Extract/SourceExtraction.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-16 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215574.
SureYeaah added a comment.

Fixed bug in getLocType


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -599,6 +599,115 @@
 R"cpp(const char * x = "test")cpp");
 }
 
+TWEAK_TEST(ExtractFunction);
+TEST_F(ExtractFunctionTest, PrepareFunctionTest) {
+  Header = R"cpp(
+#define F(BODY) void FFF() { BODY }
+  )cpp";
+  Context = Function;
+  EXPECT_AVAILABLE(R"cpp(
+[[int sum = 0;
+for(;;)
+  sum++;]]
+for(int i = 0; i < 5; i++) {
+  sum += i;
+}
+  )cpp");
+  EXPECT_AVAILABLE(R"cpp([[int x;]])cpp");
+  // TODO: Add tests for macros after selectionTree works properly for macros.
+  // EXPECT_AVAILABLE(R"cpp( F (int x = 0; [[x = 1;]])cpp");
+  // FIXME: This should be unavailable since partially selected but
+  // selectionTree doesn't always work correctly for VarDecls.
+  //EXPECT_UNAVAILABLE(R"cpp(int [[x = 0]];)cpp");
+  EXPECT_UNAVAILABLE(R"cpp(
+int sum = 0;
+for(;;)
+  [[sum++;
+sum++;]]
+  )cpp");
+  // Expressions aren't extracted.
+  EXPECT_UNAVAILABLE(R"cpp(int x = 0; [[x++;]])cpp");
+  // FIXME: ExtractFunction should be unavailable inside loop construct
+  // initalizer/condition.
+  // EXPECT_UNAVAILABLE(R"cpp( for([[int i = 0; i < 5;]] i++) )cpp");
+}
+
+TEST_F(ExtractFunctionTest, PrepareMethodTest) {
+  EXPECT_UNAVAILABLE(R"cpp(
+class T {
+  void f() {
+[[int x;]]
+  }
+};
+  )cpp");
+}
+
+TEST_F(ExtractFunctionTest, ApplyTest) {
+  // We can extract from templated functions as long as no reference in the
+  // extraction depends on the template.
+  // Checks const qualifier and extraction parameters.
+  Header = R"cpp(
+  )cpp";
+  EXPECT_EQ(apply(
+R"cpp(
+struct FOO {
+  int x;
+};
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  [[a += foo.x;
+  b = c; 
+  *ptr++;
+  int d = 5 /* check if comment is extracted */ ;]]
+})cpp"),
+R"cpp(
+struct FOO {
+  int x;
+};
+void extracted(int &a, int &b, const int &c, struct FOO &foo, int * &ptr) {
+a += foo.x;
+  b = c; 
+  *ptr++;
+  int d = 5 /* check if comment is extracted */ ;
+}
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  extracted(a, b, c, foo, ptr);
+})cpp");
+  auto ShouldSucceed = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), HasSubstr("extracted"));
+  };
+  auto ShouldFail = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), StartsWith("fail:"));
+  };
+  // Ensure the last break isn't included in the Source since the end of source
+  // and beginning of break are adjacent.
+  ShouldSucceed(R"cpp(
+void f() {
+  for(;;) {
+[[{}]]break;
+  }
+}
+  )cpp");
+  // Don't extract because needs hoisting.
+  ShouldFail(R"cpp( void f() { [[int a = 5;]] a++;})cpp");
+  // Don't extract parameters that depend on template.
+  ShouldFail(R"cpp( template void f() { [[int a = N;]] })cpp");
+  ShouldFail(R"cpp( template void f() { [[T t;]] })cpp");
+  // Don't extract return
+  ShouldFail(R"cpp( int f() { int a = 5; [[return a;]]})cpp");
+  // Don't extract break and continue.
+  // FIXME: We should be able to extract this.
+  ShouldFail(R"cpp( int f() { [[for(;;) break;]]})cpp");
+  ShouldFail(R"cpp( int f() { for(;;) [[continue;]]})cpp");
+  // Don't extract when we need to make a function as a parameter.
+  ShouldFail(R"cpp( void f() { [[int a; f();]] } )cpp");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,537 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include

[PATCH] D65526: [Clangd] Initial prototype version of ExtractFunction

2019-08-16 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 215615.
SureYeaah added a comment.

Fixed semicolon bug


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65526

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -599,6 +599,117 @@
 R"cpp(const char * x = "test")cpp");
 }
 
+TWEAK_TEST(ExtractFunction);
+TEST_F(ExtractFunctionTest, PrepareFunctionTest) {
+  Header = R"cpp(
+#define F(BODY) void FFF() { BODY }
+  )cpp";
+  Context = Function;
+  EXPECT_AVAILABLE(R"cpp(
+[[int sum = 0;
+for(;;)
+  sum++;]]
+for(int i = 0; i < 5; i++) {
+  sum += i;
+}
+  )cpp");
+  EXPECT_AVAILABLE(R"cpp([[int x;]])cpp");
+  // TODO: Add tests for macros after selectionTree works properly for macros.
+  // EXPECT_AVAILABLE(R"cpp( F (int x = 0; [[x = 1;]])cpp");
+  // FIXME: This should be unavailable since partially selected but
+  // selectionTree doesn't always work correctly for VarDecls.
+  //EXPECT_UNAVAILABLE(R"cpp(int [[x = 0]];)cpp");
+  EXPECT_UNAVAILABLE(R"cpp(
+int sum = 0;
+for(;;)
+  [[sum++;
+sum++;]]
+  )cpp");
+  // Expressions aren't extracted.
+  EXPECT_UNAVAILABLE(R"cpp(int x = 0; [[x++;]])cpp");
+  // FIXME: ExtractFunction should be unavailable inside loop construct
+  // initalizer/condition.
+  // EXPECT_UNAVAILABLE(R"cpp( for([[int i = 0; i < 5;]] i++) )cpp");
+}
+
+TEST_F(ExtractFunctionTest, PrepareMethodTest) {
+  EXPECT_UNAVAILABLE(R"cpp(
+class T {
+  void f() {
+[[int x;]]
+  }
+};
+  )cpp");
+}
+
+TEST_F(ExtractFunctionTest, ApplyTest) {
+  // We can extract from templated functions as long as no reference in the
+  // extraction depends on the template.
+  // Checks const qualifier and extraction parameters.
+  Header = R"cpp(
+  )cpp";
+  EXPECT_EQ(apply(
+R"cpp(
+struct FOO {
+  int x;
+};
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  [[a += foo.x;
+  b = c; 
+  *ptr++;
+  for(;;)
+int d = 5 /* check if comment is extracted */ ;]]
+})cpp"),
+R"cpp(
+struct FOO {
+  int x;
+};
+void extracted(int &a, int &b, const int &c, struct FOO &foo, int * &ptr) {
+a += foo.x;
+  b = c; 
+  *ptr++;
+  for(;;)
+int d = 5 /* check if comment is extracted */ ;
+}
+template
+void f(int a) {
+  int b = N; T t; const int c; FOO foo;
+  int *ptr = &a;
+  extracted(a, b, c, foo, ptr);
+})cpp");
+  auto ShouldSucceed = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), HasSubstr("extracted"));
+  };
+  auto ShouldFail = [&](llvm::StringRef Code) {
+EXPECT_THAT(apply(Code), StartsWith("fail:"));
+  };
+  // Ensure the last break isn't included in the Source since the end of source
+  // and beginning of break are adjacent.
+  ShouldSucceed(R"cpp(
+void f() {
+  for(;;) {
+[[{}]]break;
+  }
+}
+  )cpp");
+  // Don't extract because needs hoisting.
+  ShouldFail(R"cpp( void f() { [[int a = 5;]] a++;})cpp");
+  // Don't extract parameters that depend on template.
+  ShouldFail(R"cpp( template void f() { [[int a = N;]] })cpp");
+  ShouldFail(R"cpp( template void f() { [[T t;]] })cpp");
+  // Don't extract return
+  ShouldFail(R"cpp( int f() { int a = 5; [[return a;]]})cpp");
+  // Don't extract break and continue.
+  // FIXME: We should be able to extract this.
+  ShouldFail(R"cpp( int f() { [[for(;;) break;]]})cpp");
+  ShouldFail(R"cpp( int f() { for(;;) [[continue;]]})cpp");
+  // Don't extract when we need to make a function as a parameter.
+  ShouldFail(R"cpp( void f() { [[int a; f();]] } )cpp");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -0,0 +1,546 @@
+//===--- ExtractFunction.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 "ClangdUnit.h"
+#include "Logger.h"
+#include "Selection.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Sourc

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-06-25 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, mgorny.
Herald added a project: clang.
SureYeaah retitled this revision from "dummy variable extraction on a function 
scope" to "[clangd] dummy variable extraction on a function scope".
Herald added subscribers: MaskRay, ilya-biryukov.

- Added extraction to a dummy variable
- using auto for the dummy variable type for now
- Works on a function scope
- Adding braces to create a compound statement not supported yet
- added unit tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -216,6 +216,207 @@
   checkTransform(ID, Input, Output);
 }
 
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  return 1;
+}
+void f() {
+  int a = 5 + [[4 * [[^xyz();
+  // FIXME: add test case for multiple variable initialization once
+  // SelectionTree commonAncestor bug is fixed
+  switch(a) {
+case 1: {
+  a = ^1;
+  break;
+}
+default: {
+  a = ^3; 
+}
+  }
+  if(a < ^3)
+if(a == 4)
+  a = 5;
+else
+  a = 6;
+  else if (a < 4) {
+a = ^4;
+  }
+  else {
+a = ^5;
+  }
+  // for loop testing
+  for(a = ^1; a > ^3+^4; a++) 
+a = 2;
+  // while testing
+  while(a < ^1) {
+^a++;
+  }
+  // do while testing
+  do
+a = 1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+void f(int b = ^1) {
+  int a = 5 + 4 * 3;
+  // switch testing
+  switch(a) {
+case 1: 
+  a = ^1;
+  break;
+default:
+  a = ^3; 
+  }
+  // if testing
+  if(a < 3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4) {
+a = 4;
+  }
+  else {
+a = 5;
+  }
+  // for loop testing
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++) 
+a = ^2;
+  // while testing
+  while(a < 1) {
+a++;
+  }
+  // do while testing
+  do
+a = ^1;
+  while(a < 3);
+  // testing in cases where braces are required
+  if (true)
+do
+  a = 1;
+while(a < ^1);
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // extraction from for loop init/cond/incr
+  {R"cpp(void forLoop() {
+   for(int a = 1; a < ^3; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp",
+   R"cpp(void forLoop() {
+   auto dummy = 3; for(int a = 1; a < dummy; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp"},
+  // extraction inside for loop body
+  {R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ a = 5 + [[4 * 3]];
+   }
+ })cpp",
+   R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ auto dummy = 4 * 3; a = 5 + dummy;
+   }
+ })cpp"},
+  // extraction inside while loop condition
+  {R"cpp(void whileLoop(int a) {
+   while(a < 5 + [[4 * 3]]) 
+ a += 1;
+ })cpp",
+   R"cpp(void whileLoop(int a) {
+   auto dummy = 4 * 3; while(a < 5 + dummy) 
+ a += 1;
+ })cpp"},
+  // extraction inside while body condition
+  {R"cpp(void whileBody(int a) {
+   while(a < 1) {
+ a += ^7 * 3;
+   }
+ })cpp",
+   R"cpp(void whileBody(int a) {
+   while(a < 1) {
+ auto dummy = 7; a += dummy * 3;
+   }
+ })cpp"},
+  // extraction inside do-while loop condition
+  {R"cpp(void doWhileLoop(int a) {
+   do
+ a += 3;
+   w

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-06-26 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked 12 inline comments as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:54
+
+// RAV subclass to find all DeclRefs in a given Stmt
+class FindDeclRefsVisitor

kadircet wrote:
> I believe this class is rather used to check if any decl referenced in an 
> expression was declared in a statement, rather then finding those declrefs.
> 
> So what about turning it inside out :D ? Something like:
> 
> ```
> bool isDeclaredIn(const DeclStmt *DS, const Expr *E, SourceManager &SM) {
>   // Collects all DelcRefs in an AST node.
>   class FindDeclRefsVisitor  {
>   public: 
> bool VisitDeclRefExpr(... *DRE) { DeclRefs.push_back(DRE); return true; }
> std::vector DeclRefs;
>   };
>   FindDeclRefsVisitor X;
>   X.TraverseStmt ...
>   for(auto *DRE : X.DeclRefs) {
>  ...
>}
>return ...;
> }
> ```
Aah, I didn't know you could declare a class inside a function. Nice.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:95
+// Returns true if we will need braces after extraction
+static bool needBraces(const SelectionTree::Node *N, const Stmt *Stm,
+   const SourceManager &M) {

kadircet wrote:
> I suppose currently this check is not doing what it claims to do(not checking 
> for whether it is the only statement and/or if there are enclosing braces).
> 
> Maybe leave it out of this patch completely?
Right now, we check whether we will need braces and if so, we don't provide an 
extraction option. Although we don't insert the braces, we still need to check 
if the extraction would require braces.

The "body" of an if, for, while etc. will either be a CompoundStmt in which 
case there are already braces or not in which case there are no braces. So if 
while going up the AST parents, we encounter a CompoundStmt, we stop there. 
Otherwise, if we encounter an if/for/while etc. Stmt, we we have 2 cases - 
Either we are in the body (e.g. do  while(...); ) or the condition part 
(e.g. if(...) or for(...)). So we check which of these two cases it is and 
accordingly decide if we need braces i.e. the body case.

So we don't need to check whether it's the only statement. Does that make sense?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:108
+// check whether to allow extraction from for(...)
+static bool checkFor(const ForStmt *F, const Expr *Exp,
+ const SourceManager &M) {

kadircet wrote:
> I believe it would be better to have a more generic check that will ensure 
> all of the delcs referenced in `Exp` are still visible in the context which 
> we'll insert the new statement. WDYT?
> 
> Were there any reasons to make it specific for `ForStmt` ?
The reason why it's specific for ForStmt (at least for now) is because only in 
ForStmt we can have declarations as well as other expressions in the for(...) 
part. For all other cases, we don't have such a scenario. WDYT?



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:137
+  N->ASTNode.get(), M)) {
+  // Check whether the expression references any variable in the for
+  // initializer and if so, we can't extract

kadircet wrote:
> what about a case like:
> ```
> for(int i=0;;) {
>   int z = [[f(i)*10]] + 5;
> }
> ```
> I believe it should be OK to extract in this case right ?
This check is only for extraction from the for(; ; ) and not 
the body of the for. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773



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


[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-06-26 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 206663.
SureYeaah marked 4 inline comments as done.
SureYeaah added a comment.

Refactored code

- Refactored code as pointed by kadircet
- Fixed crash for if statements without an else clause


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -216,6 +216,208 @@
   checkTransform(ID, Input, Output);
 }
 
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  return 1;
+}
+void f() {
+  int a = 5 + [[4 * [[^xyz();
+  // FIXME: add test case for multiple variable initialization once
+  // SelectionTree commonAncestor bug is fixed
+  switch(a) {
+case 1: {
+  a = ^1;
+  break;
+}
+default: {
+  a = ^3; 
+}
+  }
+  if(^1) {}
+  if(a < ^3)
+if(a == 4)
+  a = 5;
+else
+  a = 6;
+  else if (a < 4) {
+a = ^4;
+  }
+  else {
+a = ^5;
+  }
+  // for loop testing
+  for(a = ^1; a > ^3+^4; a++) 
+a = 2;
+  // while testing
+  while(a < ^1) {
+^a++;
+  }
+  // do while testing
+  do
+a = 1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+void f(int b = ^1) {
+  int a = 5 + 4 * 3;
+  // switch testing
+  switch(a) {
+case 1: 
+  a = ^1;
+  break;
+default:
+  a = ^3; 
+  }
+  // if testing
+  if(a < 3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4) {
+a = 4;
+  }
+  else {
+a = 5;
+  }
+  // for loop testing
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++) 
+a = ^2;
+  // while testing
+  while(a < 1) {
+a++;
+  }
+  // do while testing
+  do
+a = ^1;
+  while(a < 3);
+  // testing in cases where braces are required
+  if (true)
+do
+  a = 1;
+while(a < ^1);
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // extraction from for loop init/cond/incr
+  {R"cpp(void forLoop() {
+   for(int a = 1; a < ^3; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp",
+   R"cpp(void forLoop() {
+   auto dummy = 3; for(int a = 1; a < dummy; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp"},
+  // extraction inside for loop body
+  {R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ a = 5 + [[4 * 3]];
+   }
+ })cpp",
+   R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ auto dummy = 4 * 3; a = 5 + dummy;
+   }
+ })cpp"},
+  // extraction inside while loop condition
+  {R"cpp(void whileLoop(int a) {
+   while(a < 5 + [[4 * 3]]) 
+ a += 1;
+ })cpp",
+   R"cpp(void whileLoop(int a) {
+   auto dummy = 4 * 3; while(a < 5 + dummy) 
+ a += 1;
+ })cpp"},
+  // extraction inside while body condition
+  {R"cpp(void whileBody(int a) {
+   while(a < 1) {
+ a += ^7 * 3;
+   }
+ })cpp",
+   R"cpp(void whileBody(int a) {
+   while(a < 1) {
+ auto dummy = 7; a += dummy * 3;
+   }
+ })cpp"},
+  // extraction inside do-while loop condition
+  {R"cpp(void doWhileLoop(int a) {
+   do
+ a += 3;
+   while(a < ^1);
+ })cpp",
+   R"cpp(void doWhileLoop(int a) {
+   auto dummy = 1; do
+ a += 3;
+   while(a < dummy);
+ })cpp"},
+  // extraction inside do-while body

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-06-27 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked 14 inline comments as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:173
+  // give up if extraction will take a variable out of scope
+  if (!extractionAllowed(ParStmt, N, M))
+break;

sammccall wrote:
> here you're traversing the whole Expr to find the referenced decls at each 
> iteration of this loop.
> Can you analyse the expr just once, and reuse the list of decls?
I thought it'll only be analyzed once but actually it's at max twice in the 
case where the selected expression is a part of a DeclStmt in the  of a 
ForStmt.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773



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


[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-06-28 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207084.
SureYeaah added a comment.

[Clangd] Refactored code

- Created new class Extract to store information about the expression being 
extracted.
- Doesn't fix all of previous comments

Looking for comments on the new class stucture


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -239,13 +239,13 @@
   checkNotAvailable(ID, "/*c^omment*/ int foo() return 2 ^ + 2; }");
 
   const char *Input = "int x = 2 ^+ 2;";
-  auto result = getMessage(ID, Input);
-  EXPECT_THAT(result, ::testing::HasSubstr("BinaryOperator"));
-  EXPECT_THAT(result, ::testing::HasSubstr("'+'"));
-  EXPECT_THAT(result, ::testing::HasSubstr("|-IntegerLiteral"));
-  EXPECT_THAT(result,
+  auto Result = getMessage(ID, Input);
+  EXPECT_THAT(Result, ::testing::HasSubstr("BinaryOperator"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("'+'"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("|-IntegerLiteral"));
+  EXPECT_THAT(Result,
   ::testing::HasSubstr(" 'int' 2\n`-IntegerLiteral"));
-  EXPECT_THAT(result, ::testing::HasSubstr(" 'int' 2"));
+  EXPECT_THAT(Result, ::testing::HasSubstr(" 'int' 2"));
 }
 
 TEST(TweakTest, ShowSelectionTree) {
@@ -277,6 +277,209 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  return 1;
+}
+void f() {
+  int a = 5 + [[4 * [[^xyz();
+  int x = ^1, y = x + 1, z = ^1;
+  switch(a) {
+case 1: {
+  a = ^1;
+  break;
+}
+default: {
+  a = ^3; 
+}
+  }
+  // if testing
+  if(^1) {}
+  if(a < ^3)
+if(a == 4)
+  a = 5;
+else
+  a = 6;
+  else if (a < 4) {
+a = ^4;
+  }
+  else {
+a = ^5;
+  }
+  // for loop testing
+  for(a = ^1; a > ^3+^4; a++) 
+a = 2;
+  // while testing
+  while(a < ^1) {
+^a++;
+  }
+  // do while testing
+  do
+a = 1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+void f(int b = ^1) {
+  int a = 5 + 4 * 3;
+  // check whether extraction breaks scope
+  int x = 1, y = ^x + 1;
+  // switch testing
+  switch(a) {
+case 1: 
+  a = ^1;
+  break;
+default:
+  a = ^3; 
+  }
+  // if testing
+  if(a < 3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4) {
+a = 4;
+  }
+  else {
+a = 5;
+  }
+  // for loop testing
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++) 
+a = ^2;
+  // while testing
+  while(a < 1) {
+a++;
+  }
+  // do while testing
+  do
+a = ^1;
+  while(a < 3);
+  // testing in cases where braces are required
+  if (true)
+do
+  a = 1;
+while(a < ^1);
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // extraction from for loop init/cond/incr
+  {R"cpp(void forLoop() {
+   for(int a = 1; a < ^3; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp",
+   R"cpp(void forLoop() {
+   auto dummy = 3; for(int a = 1; a < dummy; a++) {
+ a = 5 + 4 * 3;
+   }
+ })cpp"},
+  // extraction inside for loop body
+  {R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ a = 5 + [[4 * 3]];
+   }
+ })cpp",
+   R"cpp(void forBody() {
+   for(int a = 1; a < 3; a++) {
+ auto dummy = 4 * 3; a = 5 + dummy;
+   }
+ })cpp"},
+  // extraction inside while loop condition
+  {R"cpp(void whileLoop(int a) {
+   while(a < 5 + [[4 * 3]]) 
+ a += 1;
+   

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah marked 13 inline comments as done.
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:71
+}
+std::vector Extract::getReferencedDecls() {
+  // RAV subclass to find all DeclRefs in a given Stmt

kadircet wrote:
> this method doesn't use class state, maybe move it out-of-class to a function?
It uses the expr


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773



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


[PATCH] D63989: Summary: [Clangd] Added hidden flag --disable-tweaks to disable tweaks- Only for testing purposes

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/fixits-duplication.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
@@ -278,6 +278,11 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::opt DisableTweaks(
+"disable-tweaks",
+llvm::cl::desc("Disable tweak diagnostics for testing purposes."),
+llvm::cl::init(false), llvm::cl::Hidden);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -476,7 +481,7 @@
   Opts.StaticIndex = StaticIdx.get();
   Opts.AsyncThreadsCount = WorkerThreadsCount;
   Opts.HiddenFeatures = HiddenFeatures;
-
+  Opts.DisableTweaks = DisableTweaks;
   clangd::CodeCompleteOptions CCOpts;
   CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
   CCOpts.Limit = LimitResults;
Index: clang-tools-extra/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/clangd/test/fixits-duplication.test
+++ clang-tools-extra/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr --disable-tweaks < 
%s | FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -140,6 +140,9 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Disable tweaks for testing purposes
+bool DisableTweaks = false;
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,6 +316,7 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
+  bool DisableTweaks = false;
   
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  DisableTweaks(Opts.DisableTweaks),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (DisableTweaks || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -278,6 +278,11 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::opt DisableTweaks(
+"disable-tweaks",
+llvm::cl::desc("Disable tweak diagnostics for testing purposes."),
+llvm::cl::init(false), llvm::cl::Hidden);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -476,7 +481,7 @@
   Opts.StaticIndex = StaticIdx.get();
   Opts.AsyncThreadsCount = WorkerThreadsCount;
   Opts.HiddenFeatures = HiddenFeatures;
-
+  Opts.DisableTweaks = DisableTweaks;
   clangd::CodeCompleteOptions CCOpts;
   CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
   CCOpts.Limit = LimitResults;
Index: clang-t

[PATCH] D63989: Summary: [Clangd] Added hidden flag --disable-tweaks to disable tweaks

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207313.
SureYeaah added a comment.

Replaced the boolean flag with a list of tweaks flag


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/fixits-duplication.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
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -476,7 +482,7 @@
   Opts.StaticIndex = StaticIdx.get();
   Opts.AsyncThreadsCount = WorkerThreadsCount;
   Opts.HiddenFeatures = HiddenFeatures;
-
+  // Opts.TweakFilter = Tweaks;
   clangd::CodeCompleteOptions CCOpts;
   CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
   CCOpts.Limit = LimitResults;
@@ -533,6 +539,15 @@
   }
   Opts.SuggestMissingIncludes = SuggestMissingIncludes;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
+  Opts.TweakFilter = [&](llvm::StringRef TweakToSearch) {
+// return true if any tweak matches the TweakToSearch
+for (auto Tweak : TweakList) {
+  if (TweakToSearch == Tweak)
+return true;
+}
+// return true if TweakList is not provided i.e. allow all tweaks
+return !TweakList.getNumOccurrences();
+  };
   llvm::Optional OffsetEncodingFromFlag;
   if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
 OffsetEncodingFromFlag = ForceOffsetEncoding;
Index: clang-tools-extra/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/clangd/test/fixits-duplication.test
+++ clang-tools-extra/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr -tweaks="" < %s | 
FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -140,6 +140,10 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Returns true if the StringRef is a tweak that should be enabled
+std::function TweakFilter;
+
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,7 +317,8 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-  
+   
+  std::function TweakFilter;
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
   CachedCompletionFuzzyFindRequestByFile;
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  TweakFilter(Opts.TweakFilter),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (!TweakFilter(T->id()) || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdM

[PATCH] D63989: [Clangd] Added hidden command line option -tweaks to specify which tweaks to enable

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207321.
SureYeaah added a comment.

Removed extra comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/fixits-duplication.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
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -476,7 +482,6 @@
   Opts.StaticIndex = StaticIdx.get();
   Opts.AsyncThreadsCount = WorkerThreadsCount;
   Opts.HiddenFeatures = HiddenFeatures;
-
   clangd::CodeCompleteOptions CCOpts;
   CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
   CCOpts.Limit = LimitResults;
@@ -533,6 +538,15 @@
   }
   Opts.SuggestMissingIncludes = SuggestMissingIncludes;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
+  Opts.TweakFilter = [&](llvm::StringRef TweakToSearch) {
+// return true if any tweak matches the TweakToSearch
+for (auto Tweak : TweakList) {
+  if (TweakToSearch == Tweak)
+return true;
+}
+// return true if TweakList is not provided i.e. allow all tweaks
+return !TweakList.getNumOccurrences();
+  };
   llvm::Optional OffsetEncodingFromFlag;
   if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
 OffsetEncodingFromFlag = ForceOffsetEncoding;
Index: clang-tools-extra/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/clangd/test/fixits-duplication.test
+++ clang-tools-extra/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr -tweaks="" < %s | 
FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -140,6 +140,10 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Returns true if the StringRef is a tweak that should be enabled
+std::function TweakFilter;
+
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,7 +317,8 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-  
+   
+  std::function TweakFilter;
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
   CachedCompletionFuzzyFindRequestByFile;
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  TweakFilter(Opts.TweakFilter),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (!TweakFilter(T->id()) || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path

[PATCH] D63989: [Clangd] Added hidden command line option -tweaks to specify which tweaks to enable

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207323.
SureYeaah added a comment.

Whitespace formatting


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/fixits-duplication.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
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -533,6 +539,15 @@
   }
   Opts.SuggestMissingIncludes = SuggestMissingIncludes;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
+  Opts.TweakFilter = [&](llvm::StringRef TweakToSearch) {
+// return true if any tweak matches the TweakToSearch
+for (auto Tweak : TweakList) {
+  if (TweakToSearch == Tweak)
+return true;
+}
+// return true if TweakList is not provided i.e. allow all tweaks
+return !TweakList.getNumOccurrences();
+  };
   llvm::Optional OffsetEncodingFromFlag;
   if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
 OffsetEncodingFromFlag = ForceOffsetEncoding;
Index: clang-tools-extra/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/clangd/test/fixits-duplication.test
+++ clang-tools-extra/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr -tweaks="" < %s | 
FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -140,6 +140,10 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Returns true if the StringRef is a tweak that should be enabled
+std::function TweakFilter;
+
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,7 +317,8 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-  
+   
+  std::function TweakFilter;
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
   CachedCompletionFuzzyFindRequestByFile;
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  TweakFilter(Opts.TweakFilter),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (!TweakFilter(T->id()) || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Su

[PATCH] D63989: [Clangd] Added hidden command line option -tweaks to specify which tweaks to enable

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207358.
SureYeaah marked 3 inline comments as done.
SureYeaah added a comment.

Refactored code


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/test/fixits-duplication.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
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -533,6 +539,11 @@
   }
   Opts.SuggestMissingIncludes = SuggestMissingIncludes;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
+  if (TweakList.getNumOccurrences())
+Opts.TweakFilter = [&](llvm::StringRef TweakToSearch) {
+  // return true if any tweak matches the TweakToSearch
+  return llvm::find(TweakList, TweakToSearch) != TweakList.end();
+};
   llvm::Optional OffsetEncodingFromFlag;
   if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
 OffsetEncodingFromFlag = ForceOffsetEncoding;
Index: clang-tools-extra/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/clangd/test/fixits-duplication.test
+++ clang-tools-extra/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr -tweaks="" < %s | 
FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -140,6 +140,9 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Returns true if the StringRef is a tweak that should be enabled
+std::function TweakFilter = [](llvm::StringRef 
TweakToSearch) {return true;};
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,7 +316,9 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-  
+   
+  std::function TweakFilter;
+
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
   CachedCompletionFuzzyFindRequestByFile;
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  TweakFilter(Opts.TweakFilter),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (!TweakFilter(T->id()) || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }


Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test U

[PATCH] D63989: [Clangd] Added hidden command line option -tweaks to specify which tweaks to enable

2019-07-01 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL364809: Summary: [Clangd] Added hidden command line option 
-tweaks to specify which… (authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D63989?vs=207358&id=207363#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D63989

Files:
  clang-tools-extra/trunk/clangd/ClangdServer.cpp
  clang-tools-extra/trunk/clangd/ClangdServer.h
  clang-tools-extra/trunk/clangd/test/fixits-duplication.test
  clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp


Index: clang-tools-extra/trunk/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/trunk/clangd/test/fixits-duplication.test
+++ clang-tools-extra/trunk/clangd/test/fixits-duplication.test
@@ -1,4 +1,4 @@
-# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr < %s | FileCheck 
-strict-whitespace %s
+# RUN: clangd -lit-test 
-clang-tidy-checks=modernize-use-nullptr,hicpp-use-nullptr -tweaks="" < %s | 
FileCheck -strict-whitespace %s
 
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{,"trace":"off"}}
 ---
 
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///foo.cpp","languageId":"cpp","version":1,"text":"void
 foo() { char* p = 0; }"}}}
Index: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
===
--- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
@@ -278,6 +278,12 @@
 "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"),
 llvm::cl::CommaSeparated);
 
+static llvm::cl::list TweakList(
+"tweaks",
+llvm::cl::desc(
+"Specify a list of Tweaks to enable (only for clangd developers)."),
+llvm::cl::Hidden, llvm::cl::CommaSeparated);
+
 namespace {
 
 /// \brief Supports a test URI scheme with relaxed constraints for lit tests.
@@ -533,6 +539,11 @@
   }
   Opts.SuggestMissingIncludes = SuggestMissingIncludes;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
+  if (TweakList.getNumOccurrences())
+Opts.TweakFilter = [&](llvm::StringRef TweakToSearch) {
+  // return true if any tweak matches the TweakToSearch
+  return llvm::find(TweakList, TweakToSearch) != TweakList.end();
+};
   llvm::Optional OffsetEncodingFromFlag;
   if (ForceOffsetEncoding != OffsetEncoding::UnsupportedEncoding)
 OffsetEncodingFromFlag = ForceOffsetEncoding;
Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp
===
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp
@@ -102,6 +102,7 @@
   GetClangTidyOptions(Opts.GetClangTidyOptions),
   SuggestMissingIncludes(Opts.SuggestMissingIncludes),
   EnableHiddenFeatures(Opts.HiddenFeatures),
+  TweakFilter(Opts.TweakFilter),
   WorkspaceRoot(Opts.WorkspaceRoot),
   // Pass a callback into `WorkScheduler` to extract symbols from a newly
   // parsed file and rebuild the file index synchronously each time an AST
@@ -333,7 +334,7 @@
   return CB(Selection.takeError());
 std::vector Res;
 for (auto &T : prepareTweaks(*Selection)) {
-  if (T->hidden() && !EnableHiddenFeatures)
+  if (!TweakFilter(T->id()) || (T->hidden() && !EnableHiddenFeatures))
 continue;
   Res.push_back({T->id(), T->title(), T->intent()});
 }
Index: clang-tools-extra/trunk/clangd/ClangdServer.h
===
--- clang-tools-extra/trunk/clangd/ClangdServer.h
+++ clang-tools-extra/trunk/clangd/ClangdServer.h
@@ -140,6 +140,9 @@
 
 /// Enable semantic highlighting features.
 bool SemanticHighlighting = false;
+
+/// Returns true if the StringRef is a tweak that should be enabled
+std::function TweakFilter = [](llvm::StringRef 
TweakToSearch) {return true;};
   };
   // Sensible default options for use in tests.
   // Features like indexing must be enabled if desired.
@@ -313,7 +316,9 @@
   // can be caused by missing includes (e.g. member access in incomplete type).
   bool SuggestMissingIncludes = false;
   bool EnableHiddenFeatures = false;
-  
+   
+  std::function TweakFilter;
+
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap>
   CachedCompletionFuzzyFindRequestByFile;


Index: clang-tools-extra/trunk/clangd/test/fixits-duplication.test
===
--- clang-tools-extra/trunk/clangd/test/fixits-duplication.test
+++ clang-tools-extra/trunk/clangd/test/fixits-duplicatio

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-02 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 207522.
SureYeaah added a comment.

Removed check for braces and fixed  code for finding insertionpoint


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -239,13 +239,13 @@
   checkNotAvailable(ID, "/*c^omment*/ int foo() return 2 ^ + 2; }");
 
   const char *Input = "int x = 2 ^+ 2;";
-  auto result = getMessage(ID, Input);
-  EXPECT_THAT(result, ::testing::HasSubstr("BinaryOperator"));
-  EXPECT_THAT(result, ::testing::HasSubstr("'+'"));
-  EXPECT_THAT(result, ::testing::HasSubstr("|-IntegerLiteral"));
-  EXPECT_THAT(result,
+  auto Result = getMessage(ID, Input);
+  EXPECT_THAT(Result, ::testing::HasSubstr("BinaryOperator"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("'+'"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("|-IntegerLiteral"));
+  EXPECT_THAT(Result,
   ::testing::HasSubstr(" 'int' 2\n`-IntegerLiteral"));
-  EXPECT_THAT(result, ::testing::HasSubstr(" 'int' 2"));
+  EXPECT_THAT(Result, ::testing::HasSubstr(" 'int' 2"));
 }
 
 TEST(TweakTest, ShowSelectionTree) {
@@ -277,6 +277,128 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  return ^1;
+}
+void f() {
+  int a = 5 + [[4 * xyz^()]];
+  if(1)
+int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+  switch(a)
+case 1:
+  a = ^1;
+  break;
+default:
+  a = ^3;
+  // if without else
+  if(^1) {}
+  // if with else
+  if(a < ^3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4)
+a = ^4;
+  else
+a = ^5;
+  // for loop testing
+  for(a = ^1; a > ^3^+^4; a++)
+a = ^2;
+  // while testing
+  while(a < ^1)
+^a++;
+  // do while testing
+  do
+a = ^1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+int xyz(int a = ^1) {
+  return 1;
+  class T {
+T(int a = ^1) {};
+int xyz = ^1;
+  };
+}
+void f(int b = ^1) {
+  // we don't want to extract just the function
+  int a = 5 + 4 * [[xyz]]();
+  // if
+  if(1)
+int x = 1, y = a + 1, a = 1, z = ^a + 1;
+  if(int a = 1)
+if(^a == 4)
+  a = ^a ^+ 1;
+  // for loop testing
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
+a = ^a ^+ 1;
+  // lambda testing
+  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // extraction from case inside nested structure
+  {R"cpp(void f(int a) {
+   if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = [[1 + 2]];
+ break;
+   default:
+ break;
+   }
+ })cpp",
+   R"cpp(void f(int a) {
+   auto dummy = 1 + 2; if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = dummy;
+ break;
+   default:
+ break;
+   }
+ })cpp"},
+  // ensure InsertionPoint isn't inside a macro
+  {R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   auto dummy = 3; if(1)
+LOOP(5 + dummy)
+ })cpp"},
+  // FIXME: Doesn't work because bug in selection tree
+  /*{R"cpp(#define PLUS(x) x++
+ void f(int a) {
+   PLUS(^a);
+ })

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-05 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 208174.
SureYeaah marked 21 inline comments as done.
SureYeaah added a comment.

Added whitelist for computeInsertionPoint


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.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
@@ -239,13 +239,13 @@
   checkNotAvailable(ID, "/*c^omment*/ int foo() return 2 ^ + 2; }");
 
   const char *Input = "int x = 2 ^+ 2;";
-  auto result = getMessage(ID, Input);
-  EXPECT_THAT(result, ::testing::HasSubstr("BinaryOperator"));
-  EXPECT_THAT(result, ::testing::HasSubstr("'+'"));
-  EXPECT_THAT(result, ::testing::HasSubstr("|-IntegerLiteral"));
-  EXPECT_THAT(result,
+  auto Result = getMessage(ID, Input);
+  EXPECT_THAT(Result, ::testing::HasSubstr("BinaryOperator"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("'+'"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("|-IntegerLiteral"));
+  EXPECT_THAT(Result,
   ::testing::HasSubstr(" 'int' 2\n`-IntegerLiteral"));
-  EXPECT_THAT(result, ::testing::HasSubstr(" 'int' 2"));
+  EXPECT_THAT(Result, ::testing::HasSubstr(" 'int' 2"));
 }
 
 TEST(TweakTest, ShowSelectionTree) {
@@ -277,6 +277,136 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  // return statement
+  return ^1;
+}
+void f() {
+  int a = 5 + [[4 ^* ^xyz^()]];
+  // multivariable initialization
+  if(1)
+int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+  // if without else
+  if(^1) {}
+  // if with else
+  if(a < ^3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4)
+a = ^4;
+  else
+a = ^5;
+  // for loop 
+  for(a = ^1; a > ^3^+^4; a++)
+a = ^2;
+  // while 
+  while(a < ^1)
+^a++;
+  // do while 
+  do
+a = ^1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+int xyz(int a = ^1) {
+  return 1;
+  class T {
+T(int a = ^1) {};
+int xyz = ^1;
+  };
+}
+// function default argument
+void f(int b = ^1) {
+  // invalid expression checking;
+  auto i = new int, j = new int;
+  de^lete i^, del^ete j;
+  // if
+  if(1)
+int x = 1, y = a + 1, a = 1, z = ^a + 1;
+  if(int a = 1)
+if(^a == 4)
+  a = ^a ^+ 1;
+  // for loop 
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
+a = ^a ^+ 1;
+  // lambda 
+  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // FIXME: extraction from switch case
+  /*{R"cpp(void f(int a) {
+   if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = [[1 + 2]];
+ break;
+   default:
+ break;
+   }
+ })cpp",
+   R"cpp(void f(int a) {
+   auto dummy = 1 + 2; if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = dummy;
+ break;
+   default:
+ break;
+   }
+ })cpp"},*/
+  // ensure InsertionPoint isn't inside a macro
+  {R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   auto dummy = 3; if(1)
+LOOP(5 + dummy)
+ })cpp"},
+  // label and attribute testing
+  {R"cpp(void f(int a) {
+label: [ [gsl::suppress("type")] ] for (;;) a = ^1;
+ })cpp",
+   R"cpp(voi

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-05 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:90
+bool isAFunctionRef(const clang::Expr *Expr) {
+  const clang::DeclRefExpr *DeclRef = dyn_cast_or_null(Expr);
+  if (DeclRef && isa(DeclRef->getDecl()))

sammccall wrote:
> sammccall wrote:
> > Extracting just a declrefexpr (and replacing it with another declrefexpr) 
> > doesn't seem useful. Any reason to only do this for functions, rather than 
> > all declrefexprs?
> a syntactically similar case is MemberExpr where isImplicitAccess() is true. 
> (This is referring to a method of the current class, without qualification)
Extracting
  int a = [[f]]();
yields
  auto dummy = f;
  int a = dummy();

I thought this should be prevented. But now I see there's no need to do that.
I'll add a triviality check if needed in the next patch.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D63773



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


[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-08 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

Fixed SelectionTree bug for macros

- Fixed SelectionTree claimRange for macros and template instantiations
- Fixed SelectionTree unit tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,13 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
   SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  SR = getFileRange(SR, SM, LangOpts);
+  return Range{offsetToPosition(Buffer, SM.getFileOffset(SR.getBegin())),
+   offsetToPosition(Buffer, SM.getFileOffset(SR.getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +142,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,7 +306,7 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
   )cpp",
   };
   for (const char *C : Cases) {
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/SHA1.h"
 
 namespace clang {
@@ -201,6 +201,9 @@
 std::vector visibleNamespaces(llvm::StringRef Code,
const format::FormatStyle &Style);
 
+// Return the FileRange for a given range where the ends can be in different
+// files. Note that the end of the FileRange is the end of the last token.
+SourceRange getFileRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts);
 } // namespace clangd
 } // namespace clang
 #endif
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,7 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -24,6 +25,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
 #include 
 
 namespace clang {
@@ -444,8 +446,8 @@
 namespace {
 enum NamespaceEvent {
   BeginNamespace, // namespace  {. Payload is resolved .
-  EndNamespace,   // } // namespace .  Payload is resolved *outer* namespace.
-  UsingDirective  // using namespace . Payload is unresolved .
+  EndNamespace,  // } // namespace .  Payload is resolved *outer* namespace.
+  UsingDirective // using namespace . Payload is unresolved .
 };
 // Scans C++ source code for constructs that change the visible namespaces.
 void parseNamespaceEvents(
@@ -468,7 +470,7 @@
   std::string NSName;
 
   lex(Code, Style, [&](const clang::Token &Tok) {
-switch(Tok.getKind()) {
+switch (Tok.getKind()) {
 case tok::raw_identifier:
   // In raw mode, this could 

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-08 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 208387.
SureYeaah added a comment.

Removed debugging code


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,13 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
   SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  SR = getFileRange(SR, SM, LangOpts);
+  return Range{offsetToPosition(Buffer, SM.getFileOffset(SR.getBegin())),
+   offsetToPosition(Buffer, SM.getFileOffset(SR.getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +142,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,7 +306,7 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
   )cpp",
   };
   for (const char *C : Cases) {
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/SHA1.h"
 
 namespace clang {
@@ -201,6 +201,9 @@
 std::vector visibleNamespaces(llvm::StringRef Code,
const format::FormatStyle &Style);
 
+// Return the FileRange for a given range where the ends can be in different
+// files. Note that the end of the FileRange is the end of the last token.
+SourceRange getFileRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts);
 } // namespace clangd
 } // namespace clang
 #endif
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,7 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -24,6 +25,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
 #include 
 
 namespace clang {
@@ -444,8 +446,8 @@
 namespace {
 enum NamespaceEvent {
   BeginNamespace, // namespace  {. Payload is resolved .
-  EndNamespace,   // } // namespace .  Payload is resolved *outer* namespace.
-  UsingDirective  // using namespace . Payload is unresolved .
+  EndNamespace,  // } // namespace .  Payload is resolved *outer* namespace.
+  UsingDirective // using namespace . Payload is unresolved .
 };
 // Scans C++ source code for constructs that change the visible namespaces.
 void parseNamespaceEvents(
@@ -468,7 +470,7 @@
   std::string NSName;
 
   lex(Code, Style, [&](const clang::Token &Tok) {
-switch(Tok.getKind()) {
+switch (Tok.getKind()) {
 case tok::raw_identifier:
   // In raw mode, this could be a keyword or a name.
   switch (State) {
@@ -570,40 +572,37 @@
   // Map from namespace to (resolved) namespaces introduced via using directive.
   llvm::StringMap> 

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-08 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 208389.
SureYeaah added a comment.

Removed extra includes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/SourceCode.cpp
  clang-tools-extra/clangd/SourceCode.h
  clang-tools-extra/clangd/unittests/SelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,13 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
   SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  SR = getFileRange(SR, SM, LangOpts);
+  return Range{offsetToPosition(Buffer, SM.getFileOffset(SR.getBegin())),
+   offsetToPosition(Buffer, SM.getFileOffset(SR.getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +142,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,7 +306,7 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
   )cpp",
   };
   for (const char *C : Cases) {
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/SHA1.h"
 
 namespace clang {
@@ -201,6 +201,9 @@
 std::vector visibleNamespaces(llvm::StringRef Code,
const format::FormatStyle &Style);
 
+// Return the FileRange for a given range where the ends can be in different
+// files. Note that the end of the FileRange is the end of the last token.
+SourceRange getFileRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts);
 } // namespace clangd
 } // namespace clang
 #endif
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,7 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -444,8 +445,8 @@
 namespace {
 enum NamespaceEvent {
   BeginNamespace, // namespace  {. Payload is resolved .
-  EndNamespace,   // } // namespace .  Payload is resolved *outer* namespace.
-  UsingDirective  // using namespace . Payload is unresolved .
+  EndNamespace,  // } // namespace .  Payload is resolved *outer* namespace.
+  UsingDirective // using namespace . Payload is unresolved .
 };
 // Scans C++ source code for constructs that change the visible namespaces.
 void parseNamespaceEvents(
@@ -468,7 +469,7 @@
   std::string NSName;
 
   lex(Code, Style, [&](const clang::Token &Tok) {
-switch(Tok.getKind()) {
+switch (Tok.getKind()) {
 case tok::raw_identifier:
   // In raw mode, this could be a keyword or a name.
   switch (State) {
@@ -570,40 +571,37 @@
   // Map from namespace to (resolved) namespaces introduced via using directive.
   llvm::StringMap> UsingDirectives;
 
-  parseNamespaceEvents(Code, Style,
-   [&](NamespaceEvent Event, llvm::StringRef NS) {
- switch (Event) {
-   

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-09 Thread Shaurya Gupta via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
SureYeaah marked 8 inline comments as done.
Closed by commit rL365453: dummy variable extraction on a function scope 
(authored by SureYeaah, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D63773?vs=208174&id=208626#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D63773

Files:
  clang-tools-extra/trunk/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/trunk/clangd/refactor/tweaks/ExtractVariable.cpp
  clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp
@@ -239,13 +239,13 @@
   checkNotAvailable(ID, "/*c^omment*/ int foo() return 2 ^ + 2; }");
 
   const char *Input = "int x = 2 ^+ 2;";
-  auto result = getMessage(ID, Input);
-  EXPECT_THAT(result, ::testing::HasSubstr("BinaryOperator"));
-  EXPECT_THAT(result, ::testing::HasSubstr("'+'"));
-  EXPECT_THAT(result, ::testing::HasSubstr("|-IntegerLiteral"));
-  EXPECT_THAT(result,
+  auto Result = getMessage(ID, Input);
+  EXPECT_THAT(Result, ::testing::HasSubstr("BinaryOperator"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("'+'"));
+  EXPECT_THAT(Result, ::testing::HasSubstr("|-IntegerLiteral"));
+  EXPECT_THAT(Result,
   ::testing::HasSubstr(" 'int' 2\n`-IntegerLiteral"));
-  EXPECT_THAT(result, ::testing::HasSubstr(" 'int' 2"));
+  EXPECT_THAT(Result, ::testing::HasSubstr(" 'int' 2"));
 }
 
 TEST(TweakTest, ShowSelectionTree) {
@@ -277,6 +277,136 @@
   const char *Input = "struct ^X { int x; int y; }";
   EXPECT_THAT(getMessage(ID, Input), ::testing::HasSubstr("0 |   int x"));
 }
+TEST(TweakTest, ExtractVariable) {
+  llvm::StringLiteral ID = "ExtractVariable";
+  checkAvailable(ID, R"cpp(
+int xyz() {
+  // return statement
+  return ^1;
+}
+void f() {
+  int a = 5 + [[4 ^* ^xyz^()]];
+  // multivariable initialization
+  if(1)
+int x = ^1, y = ^a + 1, a = ^1, z = a + 1;
+  // if without else
+  if(^1) {}
+  // if with else
+  if(a < ^3)
+if(a == ^4)
+  a = ^5;
+else
+  a = ^6;
+  else if (a < ^4)
+a = ^4;
+  else
+a = ^5;
+  // for loop 
+  for(a = ^1; a > ^3^+^4; a++)
+a = ^2;
+  // while 
+  while(a < ^1)
+^a++;
+  // do while 
+  do
+a = ^1;
+  while(a < ^3);
+}
+  )cpp");
+  checkNotAvailable(ID, R"cpp(
+int xyz(int a = ^1) {
+  return 1;
+  class T {
+T(int a = ^1) {};
+int xyz = ^1;
+  };
+}
+// function default argument
+void f(int b = ^1) {
+  // void expressions
+  auto i = new int, j = new int;
+  de^lete i^, del^ete j;
+  // if
+  if(1)
+int x = 1, y = a + 1, a = 1, z = ^a + 1;
+  if(int a = 1)
+if(^a == 4)
+  a = ^a ^+ 1;
+  // for loop 
+  for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++)
+a = ^a ^+ 1;
+  // lambda 
+  auto lamb = [&^a, &^b](int r = ^1) {return 1;}
+}
+  )cpp");
+  // vector of pairs of input and output strings
+  const std::vector>
+  InputOutputs = {
+  // extraction from variable declaration/assignment
+  {R"cpp(void varDecl() {
+   int a = 5 * (4 + (3 [[- 1)]]);
+ })cpp",
+   R"cpp(void varDecl() {
+   auto dummy = (3 - 1); int a = 5 * (4 + dummy);
+ })cpp"},
+  // FIXME: extraction from switch case
+  /*{R"cpp(void f(int a) {
+   if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = [[1 + 2]];
+ break;
+   default:
+ break;
+   }
+ })cpp",
+   R"cpp(void f(int a) {
+   auto dummy = 1 + 2; if(1)
+ while(a < 1)
+   switch (1) {
+   case 1:
+ a = dummy;
+ break;
+   default:
+ break;
+   }
+ })cpp"},*/
+  // ensure InsertionPoint isn't inside a macro
+  {R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) {int a = x + 1;}
+ void f(int a) {
+   auto dummy = 3; if(1)
+LOOP(5 +

[PATCH] D63773: [clangd] dummy variable extraction on a function scope

2019-07-09 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah added inline comments.



Comment at: clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp:187
+  std::string ExtractedVarDecl = std::string("auto ") + VarName.str() + " = " +
+ ExtractionCode.str() + "; ";
+  return tooling::Replacement(SM, InsertionLoc, 0, ExtractedVarDecl);

sammccall wrote:
> nit: trailing space? should this be a newline?
Making it a newline makes writing tests harder.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D63773



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


[PATCH] D64562: [clangd] Fixed toHalfOpenFileRange

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

- Fixed toHalfOpenFileRange to work for macros as well as template

instantiations

- Added unit tests

Breaking test case for older version of toHalfOpenFileRange:
\# define FOO(X) X++
int a = 1;
int b = FOO(a);
toHalfOpenFileRange for the sourceRange of VarDecl for b returned the
wrong Range.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64562

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

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -9,6 +9,8 @@
 #include "Context.h"
 #include "Protocol.h"
 #include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Format/Format.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_os_ostream.h"
@@ -404,6 +406,40 @@
   }
 }
 
+// Test for functions toHalfOpenFileRange and getHalfOpenFileRange
+// FIXME: Need better testing support to be able to check more than just Decls.
+TEST(SourceCodeTests, HalfOpenFileRange) {
+  Annotations Test(R"cpp(
+#define FOO(X, Y) int Y = ++X
+#define BAR(X) X + 1
+template
+class P {};
+void f() {
+  $a[[P a]];
+  $b[[int b = 1]];
+  $c[[FOO(b, c)]]; 
+  $d[[FOO(BAR(BAR(b)), d)]];
+}
+  )cpp");
+
+  ParsedAST AST = TestTU::withCode(Test.code()).build();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+
+  auto CheckRange = [&](llvm::StringRef Name) {
+const NamedDecl &Decl = findUnqualifiedDecl(AST, Name);
+auto FileRange = toHalfOpenFileRange(SM, LangOpts, Decl.getSourceRange());
+ASSERT_NE(FileRange, llvm::None);
+Range HalfOpenRange = sourceRangeToRange(SM, *FileRange);
+EXPECT_EQ(HalfOpenRange, Test.ranges(Name)[0]);
+  };
+
+  CheckRange("a");
+  CheckRange("b");
+  CheckRange("c");
+  CheckRange("d");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/SHA1.h"
 
 namespace clang {
@@ -65,6 +65,7 @@
 /// FIXME: This should return an error if the location is invalid.
 Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
 
+Range sourceRangeToRange(const SourceManager &SM, SourceRange SrcRange);
 /// Returns the taken range at \p TokLoc.
 llvm::Optional getTokenRange(const SourceManager &SM,
 const LangOptions &LangOpts,
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,9 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -196,6 +199,11 @@
   return P;
 }
 
+Range sourceRangeToRange(const SourceManager &SM, SourceRange SrcRange) {
+  return Range{sourceLocToPosition(SM, SrcRange.getBegin()),
+   sourceLocToPosition(SM, SrcRange.getEnd())};
+}
+
 llvm::Optional getTokenRange(const SourceManager &SM,
 const LangOptions &LangOpts,
 SourceLocation TokLoc) {
@@ -242,20 +250,93 @@
   return L == R.getEnd() || halfOpenRangeContains(Mgr, R, L);
 }
 
-llvm::Optional toHalfOpenFileRange(const SourceManager &Mgr,
+// FIXME: Here we check whether the token at the location is a greatergreater
+// (>>) token and consider it as a single greater (>). This is to get it working
+// for templates but it isn't correct for the right shift operator. We can avoid
+// this by using half open char ranges in getFileRange() but getting token
+// ending is not well supported in macroIDs.
+static unsigned getTokenLengthAtLoc(SourceLocation Loc, const SourceManager &SM,
+const LangOptions &LangOpts) {
+  Token TheTok;
+  if (!Lexer::getRawToken(Loc, TheTok, SM, LangOpts)) {
+if (TheTok.is(tok::greatergreater))
+ 

[PATCH] D64562: [clangd] Fixed toHalfOpenFileRange

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209193.
SureYeaah added a comment.

Minor fixes


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64562

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

Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -9,6 +9,8 @@
 #include "Context.h"
 #include "Protocol.h"
 #include "SourceCode.h"
+#include "TestTU.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Format/Format.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_os_ostream.h"
@@ -404,6 +406,40 @@
   }
 }
 
+// Test for functions toHalfOpenFileRange and getHalfOpenFileRange
+// FIXME: Need better testing support to be able to check more than just Decls.
+TEST(SourceCodeTests, HalfOpenFileRange) {
+  Annotations Test(R"cpp(
+#define FOO(X, Y) int Y = ++X
+#define BAR(X) X + 1
+template
+class P {};
+void f() {
+  $a[[P a]];
+  $b[[int b = 1]];
+  $c[[FOO(b, c)]]; 
+  $d[[FOO(BAR(BAR(b)), d)]];
+}
+  )cpp");
+
+  ParsedAST AST = TestTU::withCode(Test.code()).build();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
+
+  auto CheckRange = [&](llvm::StringRef Name) {
+const NamedDecl &Decl = findUnqualifiedDecl(AST, Name);
+auto FileRange = toHalfOpenFileRange(SM, LangOpts, Decl.getSourceRange());
+ASSERT_NE(FileRange, llvm::None);
+Range HalfOpenRange = sourceRangeToRange(SM, *FileRange);
+EXPECT_EQ(HalfOpenRange, Test.ranges(Name)[0]);
+  };
+
+  CheckRange("a");
+  CheckRange("b");
+  CheckRange("c");
+  CheckRange("d");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/SourceCode.h
===
--- clang-tools-extra/clangd/SourceCode.h
+++ clang-tools-extra/clangd/SourceCode.h
@@ -20,8 +20,8 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Format/Format.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/SHA1.h"
 
 namespace clang {
@@ -65,6 +65,9 @@
 /// FIXME: This should return an error if the location is invalid.
 Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc);
 
+/// Turn a SourceLocation into a pair of positions
+Range sourceRangeToRange(const SourceManager &SM, SourceRange SrcRange);
+
 /// Returns the taken range at \p TokLoc.
 llvm::Optional getTokenRange(const SourceManager &SM,
 const LangOptions &LangOpts,
Index: clang-tools-extra/clangd/SourceCode.cpp
===
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -12,6 +12,8 @@
 #include "Logger.h"
 #include "Protocol.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Format/Format.h"
@@ -196,6 +198,11 @@
   return P;
 }
 
+Range sourceRangeToRange(const SourceManager &SM, SourceRange SrcRange) {
+  return Range{sourceLocToPosition(SM, SrcRange.getBegin()),
+   sourceLocToPosition(SM, SrcRange.getEnd())};
+}
+
 llvm::Optional getTokenRange(const SourceManager &SM,
 const LangOptions &LangOpts,
 SourceLocation TokLoc) {
@@ -242,20 +249,97 @@
   return L == R.getEnd() || halfOpenRangeContains(Mgr, R, L);
 }
 
-llvm::Optional toHalfOpenFileRange(const SourceManager &Mgr,
+// FIXME: Here we check whether the token at the location is a greatergreater
+// (>>) token and consider it as a single greater (>). This is to get it working
+// for templates but it isn't correct for the right shift operator. We can avoid
+// this by using half open char ranges in getFileRange() but getting token
+// ending is not well supported in macroIDs.
+static unsigned getTokenLengthAtLoc(SourceLocation Loc, const SourceManager &SM,
+const LangOptions &LangOpts) {
+  Token TheTok;
+  if (!Lexer::getRawToken(Loc, TheTok, SM, LangOpts)) {
+if (TheTok.is(tok::greatergreater))
+  return 1;
+else
+  return TheTok.getLength();
+  }
+  return 0;
+}
+// Returns location of the last character of the token at a given loc
+static SourceLocation getLocForTokenEnd(SourceLocation BeginLoc,
+const SourceManager &SM,
+ 

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209199.
SureYeaah marked 6 inline comments as done.
SureYeaah added a comment.

Changed claimRange to use toHalfOpenFileRange


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/unittests/SelectionTests.cpp

Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,15 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
-  SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  auto FileRange =
+  toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());
+  assert(FileRange && "We should be able to get the File Range");
+  return Range{
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +144,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,8 +308,9 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
   )cpp",
+  R"cpp(int a = [[5 >^> 1]];)cpp",
   };
   for (const char *C : Cases) {
 Annotations Test(C);
Index: clang-tools-extra/clangd/Selection.cpp
===
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -8,10 +8,13 @@
 
 #include "Selection.h"
 #include "ClangdUnit.h"
+#include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
 #include "llvm/ADT/STLExtras.h"
 #include 
 
@@ -236,29 +239,29 @@
   // Perform hit-testing of a complete Node against the selection.
   // This runs for every node in the AST, and must be fast in common cases.
   // This is usually called from pop(), so we can take children into account.
+  // FIXME: Doesn't select the binary operator node in
+  //  #define FOO(X) X + 1
+  //  int a, b = [[FOO(a)]];
   SelectionTree::Selection claimRange(SourceRange S) {
 if (!S.isValid())
   return SelectionTree::Unselected;
-// getTopMacroCallerLoc() allows selection of constructs in macro args. e.g:
+// toHalfOpenFileRange() allows selection of constructs in macro args. e.g:
 //   #define LOOP_FOREVER(Body) for(;;) { Body }
 //   void IncrementLots(int &x) {
 // LOOP_FOREVER( ++x; )
 //   }
 // Selecting "++x" or "x" will do the right thing.
-auto B = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getBegin()));
-auto E = SM.getDecomposedLoc(SM.getTopMacroCallerLoc(S.getEnd()));
+auto Range = toHalfOpenFileRange(SM, LangOpts, S);
+assert(Range && "We should be able to get the File Range");
+auto B = SM.getDecomposedLoc(Range->getBegin());
+auto E = SM.getDecomposedLoc(Range->getEnd());
 // Otherwise, nodes in macro expansions can't be selected.
 if (B.first != SelFile || E.first != SelFile)
   return SelectionTree::Unselected;
 // Cheap test: is there any overlap at all between the selection and range?
-// Note that E.second is the *start* of the last token, which is why we
-// compare against the "rounded-down" SelBegin.
-if (B.second >= SelEnd || E.second < SelBeginTokenStart)
+if (B.second >= SelEnd || E.second < SelBegin)
   return SelectionTree::Unsel

[PATCH] D64329: [Clangd] Fixed SelectionTree bug for macros

2019-07-11 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 209229.
SureYeaah added a comment.

Changed a breaking test in ExtractVariable


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D64329

Files:
  clang-tools-extra/clangd/Selection.cpp
  clang-tools-extra/clangd/unittests/SelectionTests.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
@@ -381,12 +381,23 @@
}
  })cpp"},*/
   // ensure InsertionPoint isn't inside a macro
-  {R"cpp(#define LOOP(x) {int a = x + 1;}
+  // FIXME: SelectionTree needs to be fixed for macros
+  /*{R"cpp(#define LOOP(x) while (1) {a = x;}
  void f(int a) {
if(1)
 LOOP(5 + ^3)
  })cpp",
-   R"cpp(#define LOOP(x) {int a = x + 1;}
+ 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) do {x;} while(1);
+ void f(int a) {
+   if(1)
+LOOP(5 + ^3)
+ })cpp",
+   R"cpp(#define LOOP(x) do {x;} while(1);
  void f(int a) {
auto dummy = 3; if(1)
 LOOP(5 + dummy)
@@ -407,9 +418,9 @@
  void f(int a) {
auto dummy = a; PLUS(dummy);
  })cpp"},*/
-  // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b
-  // = 1; since the attr is inside the DeclStmt and the bounds of
-  // DeclStmt don't cover the attribute
+  // FIXME: Doesn't work correctly for this code since the attr is
+  // inside the DeclStmt and the bounds of DeclStmt don't cover the attr
+  // \[\[clang::uninitialized\]\] int b = 1;
   };
   for (const auto &IO : InputOutputs) {
 checkTransform(ID, IO.first, IO.second);
Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -37,15 +37,15 @@
 Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {
   if (!N)
 return Range{};
-  SourceManager &SM = AST.getSourceManager();
+  const SourceManager &SM = AST.getSourceManager();
+  const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
   StringRef Buffer = SM.getBufferData(SM.getMainFileID());
-  SourceRange SR = N->ASTNode.getSourceRange();
-  SR.setBegin(SM.getFileLoc(SR.getBegin()));
-  SR.setEnd(SM.getFileLoc(SR.getEnd()));
-  CharSourceRange R =
-  Lexer::getAsCharRange(SR, SM, AST.getASTContext().getLangOpts());
-  return Range{offsetToPosition(Buffer, SM.getFileOffset(R.getBegin())),
-   offsetToPosition(Buffer, SM.getFileOffset(R.getEnd()))};
+  auto FileRange =
+  toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());
+  assert(FileRange && "We should be able to get the File Range");
+  return Range{
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),
+  offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};
 }
 
 std::string nodeKind(const SelectionTree::Node *N) {
@@ -144,17 +144,17 @@
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ CALL_FUNC^TION(fo^o); }]]
+void bar() { [[CALL_FUNC^TION(fo^o)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
 void foo();
 #define CALL_FUNCTION(X) X()
-void bar() [[{ C^ALL_FUNC^TION(foo); }]]
+void bar() { [[C^ALL_FUNC^TION(foo)]]; }
   )cpp",
-  "CompoundStmt",
+  "CallExpr",
   },
   {
   R"cpp(
@@ -308,8 +308,9 @@
   R"cpp(
   template 
   struct unique_ptr {};
-  void foo(^$C[[unique_ptr>]]^ a) {}
+  void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}
   )cpp",
+  R"cpp(int a = [[5 >^> 1]];)cpp",
   };
   for (const char *C : Cases) {
 Annotations Test(C);
Index: clang-tools-extra/clangd/Selection.cpp
===
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -8,10 +8,13 @@
 
 #include "Selection.h"
 #include "ClangdUnit.h"
+#include "SourceCode.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 

[PATCH] D66872: [clangd] SelectionTree should mark a node as fully-selected if the only claimed tokens were early-claimed.

2019-09-28 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah accepted this revision.
SureYeaah added a comment.
This revision is now accepted and ready to land.
Herald added a subscriber: usaxena95.

Sorry about the delay. LGTM. Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D66872



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


[PATCH] D68182: [Clangd] Ensure children are always RootStmt in ExtractFunction (Fixes #153)

2019-09-28 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah created this revision.
SureYeaah added reviewers: sammccall, kadircet.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay, 
ilya-biryukov, kristof.beyls.
Herald added a project: clang.
SureYeaah edited the summary of this revision.

We weren't always checking if children are RootStmts in ExtractFunction.

For `void f([[int a]]);`, the ParmVarDecl appeared as a RootStmt since
we didn't perform the check and ended up being casted to a (null) Stmt.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D68182

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -554,7 +554,8 @@
   EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
   // Don't extract return
   EXPECT_THAT(apply(" if(true) [[return;]] "), StartsWith("fail"));
-  
+  // Shouldn't crash.
+  EXPECT_THAT(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, FileTest) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,28 +111,30 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children are RootStmts.
-return llvm::all_of(CommonAnc->Children, isRootStmt) ? CommonAnc : nullptr;
-  case SelectionTree::Selection::Partial:
-// Treat Partially selected VarDecl as completely selected since
-// SelectionTree doesn't always select VarDecls correctly.
-// FIXME: Remove this after D66872 is upstream)
-if (!CommonAnc->ASTNode.get())
-  return nullptr;
-LLVM_FALLTHROUGH;
-  case SelectionTree::Selection::Complete:
-// If the Common Ancestor is completely selected, then it's a root 
statement
-// and its parent will be unselected.
-const Node *Parent = CommonAnc->Parent;
-// If parent is a DeclStmt, even though it's unselected, we consider it a
-// root statement and return its parent. This is done because the VarDecls
-// claim the entire selection range of the Declaration and DeclStmt is
-// always unselected.
-return Parent->ASTNode.get() ? Parent->Parent : Parent;
+case SelectionTree::Selection::Partial:
+  // Treat Partially selected VarDecl as completely selected since
+  // SelectionTree doesn't always select VarDecls correctly.
+  // FIXME: Remove this after D66872 is upstream)
+  if (!CommonAnc->ASTNode.get())
+return nullptr;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Complete:
+  // If the Common Ancestor is completely selected, then it's a root 
statement
+  // and its parent will be unselected.
+  Parent = CommonAnc->Parent;
+  // If parent is a DeclStmt, even though it's unselected, we consider it a
+  // root statement and return its parent. This is done because the 
VarDecls
+  // claim the entire selection range of the Declaration and DeclStmt is
+  // always unselected.
+  if(Parent->ASTNode.get())
+Parent = Parent->Parent;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Unselected:
+  // Ensure all Children are RootStmts.
+  return llvm::all_of(Parent->Children, isRootStmt) ? Parent : nullptr;
   }
-  llvm_unreachable("Unhandled SelectionTree::Selection enum");
 }
 
 // The ExtractionZone class forms a view of the code wrt Zone.


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -554,7 +554,8 @@
   EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
   // Don't extract return
   EXPECT_THAT(apply(" if(true) [[return;]] "), StartsWith("fail"));
-  
+  // Shouldn't crash.
+  EXPECT_THAT(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, FileTest) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,28 +111,30 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children

[PATCH] D68182: [Clangd] Ensure children are always RootStmt in ExtractFunction (Fixes #153)

2019-09-28 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 93.
SureYeaah added a comment.

Added llmv_unreachable


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68182

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -554,7 +554,8 @@
   EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
   // Don't extract return
   EXPECT_THAT(apply(" if(true) [[return;]] "), StartsWith("fail"));
-  
+  // Shouldn't crash.
+  EXPECT_THAT(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, FileTest) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,26 +111,29 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children are RootStmts.
-return llvm::all_of(CommonAnc->Children, isRootStmt) ? CommonAnc : nullptr;
-  case SelectionTree::Selection::Partial:
-// Treat Partially selected VarDecl as completely selected since
-// SelectionTree doesn't always select VarDecls correctly.
-// FIXME: Remove this after D66872 is upstream)
-if (!CommonAnc->ASTNode.get())
-  return nullptr;
-LLVM_FALLTHROUGH;
-  case SelectionTree::Selection::Complete:
-// If the Common Ancestor is completely selected, then it's a root 
statement
-// and its parent will be unselected.
-const Node *Parent = CommonAnc->Parent;
-// If parent is a DeclStmt, even though it's unselected, we consider it a
-// root statement and return its parent. This is done because the VarDecls
-// claim the entire selection range of the Declaration and DeclStmt is
-// always unselected.
-return Parent->ASTNode.get() ? Parent->Parent : Parent;
+case SelectionTree::Selection::Partial:
+  // Treat Partially selected VarDecl as completely selected since
+  // SelectionTree doesn't always select VarDecls correctly.
+  // FIXME: Remove this after D66872 is upstream)
+  if (!CommonAnc->ASTNode.get())
+return nullptr;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Complete:
+  // If the Common Ancestor is completely selected, then it's a root 
statement
+  // and its parent will be unselected.
+  Parent = CommonAnc->Parent;
+  // If parent is a DeclStmt, even though it's unselected, we consider it a
+  // root statement and return its parent. This is done because the 
VarDecls
+  // claim the entire selection range of the Declaration and DeclStmt is
+  // always unselected.
+  if(Parent->ASTNode.get())
+Parent = Parent->Parent;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Unselected:
+  // Ensure all Children are RootStmts.
+  return llvm::all_of(Parent->Children, isRootStmt) ? Parent : nullptr;
   }
   llvm_unreachable("Unhandled SelectionTree::Selection enum");
 }


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -554,7 +554,8 @@
   EXPECT_THAT(apply(" [[int a = 5;]] a++; "), StartsWith("fail"));
   // Don't extract return
   EXPECT_THAT(apply(" if(true) [[return;]] "), StartsWith("fail"));
-  
+  // Shouldn't crash.
+  EXPECT_THAT(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, FileTest) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,26 +111,29 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children are RootStmts.
-return llvm::all_of(CommonAnc->Children, isRootStmt) ? CommonAnc : nullptr;
-  case SelectionTree::Selection::Partial:
-// Treat Partially selected VarDecl as completely selected since
-// SelectionTree doesn't always select VarDecls correctly.
-// FIXME: Remove this after D66872 is upstream)
-if (!CommonAnc->ASTNode.get())
-  return nullptr;
-

[PATCH] D68182: [Clangd] Ensure children are always RootStmt in ExtractFunction (Fixes #153)

2019-09-30 Thread Shaurya Gupta via Phabricator via cfe-commits
SureYeaah updated this revision to Diff 222499.
SureYeaah added a comment.

Moved Unittest


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68182

Files:
  clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.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
@@ -554,7 +554,7 @@
   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) {
@@ -631,6 +631,9 @@
 F ([[int x = 0;]])
   )cpp";
   EXPECT_EQ(apply(MacroFailInput), "unavailable");
+
+  // Shouldn't crash.
+  EXPECT_EQ(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, ControlFlow) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,26 +111,29 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children are RootStmts.
-return llvm::all_of(CommonAnc->Children, isRootStmt) ? CommonAnc : nullptr;
-  case SelectionTree::Selection::Partial:
-// Treat Partially selected VarDecl as completely selected since
-// SelectionTree doesn't always select VarDecls correctly.
-// FIXME: Remove this after D66872 is upstream)
-if (!CommonAnc->ASTNode.get())
-  return nullptr;
-LLVM_FALLTHROUGH;
-  case SelectionTree::Selection::Complete:
-// If the Common Ancestor is completely selected, then it's a root 
statement
-// and its parent will be unselected.
-const Node *Parent = CommonAnc->Parent;
-// If parent is a DeclStmt, even though it's unselected, we consider it a
-// root statement and return its parent. This is done because the VarDecls
-// claim the entire selection range of the Declaration and DeclStmt is
-// always unselected.
-return Parent->ASTNode.get() ? Parent->Parent : Parent;
+case SelectionTree::Selection::Partial:
+  // Treat Partially selected VarDecl as completely selected since
+  // SelectionTree doesn't always select VarDecls correctly.
+  // FIXME: Remove this after D66872 is upstream)
+  if (!CommonAnc->ASTNode.get())
+return nullptr;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Complete:
+  // If the Common Ancestor is completely selected, then it's a root 
statement
+  // and its parent will be unselected.
+  Parent = CommonAnc->Parent;
+  // If parent is a DeclStmt, even though it's unselected, we consider it a
+  // root statement and return its parent. This is done because the 
VarDecls
+  // claim the entire selection range of the Declaration and DeclStmt is
+  // always unselected.
+  if(Parent->ASTNode.get())
+Parent = Parent->Parent;
+  LLVM_FALLTHROUGH;
+case SelectionTree::Selection::Unselected:
+  // Ensure all Children are RootStmts.
+  return llvm::all_of(Parent->Children, isRootStmt) ? Parent : nullptr;
   }
   llvm_unreachable("Unhandled SelectionTree::Selection enum");
 }


Index: clang-tools-extra/clangd/unittests/TweakTests.cpp
===
--- clang-tools-extra/clangd/unittests/TweakTests.cpp
+++ clang-tools-extra/clangd/unittests/TweakTests.cpp
@@ -554,7 +554,7 @@
   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) {
@@ -631,6 +631,9 @@
 F ([[int x = 0;]])
   )cpp";
   EXPECT_EQ(apply(MacroFailInput), "unavailable");
+
+  // Shouldn't crash.
+  EXPECT_EQ(apply("void f([[int a]]);"), "unavailable");
 }
 
 TEST_F(ExtractFunctionTest, ControlFlow) {
Index: clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
===
--- clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
+++ clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp
@@ -111,26 +111,29 @@
 const Node *getParentOfRootStmts(const Node *CommonAnc) {
   if (!CommonAnc)
 return nullptr;
+  const Node* Parent = CommonAnc;
   switch (CommonAnc->Selected) {
-  case SelectionTree::Selection::Unselected:
-// Ensure all Children are RootStmts.
-return llvm::all_of(CommonAnc->Children, isRootStmt) ? Commo

  1   2   >