[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-12-04 Thread Alex Lorenz via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
arphaman marked an inline comment as done.
Closed by commit rG27f124445755: [clangd]  Add a tweak refactoring to wrap 
Objective-C string literals in… (authored by arphaman).

Changed prior to commit:
  https://reviews.llvm.org/D69543?vs=231799&id=232238#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543

Files:
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.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
@@ -122,6 +122,25 @@
   EXPECT_EQ(apply(Input), Output);
 }
 
+TWEAK_TEST(ObjCLocalizeStringLiteral);
+TEST_F(ObjCLocalizeStringLiteralTest, Test) {
+  ExtraArgs.push_back("-x");
+  ExtraArgs.push_back("objective-c");
+
+  // Ensure the the action can be initiated in the string literal.
+  EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^";)");
+
+  // Ensure that the action can't be initiated in other places.
+  EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])");
+
+  // Ensure that the action is not available for regular C strings.
+  EXPECT_UNAVAILABLE(R"(const char * x= "^test";)");
+
+  const char *Input = R"(id x = [[@"test"]];)";
+  const char *Output = R"(id x = NSLocalizedString(@"test", @"");)";
+  EXPECT_EQ(apply(Input), Output);
+}
+
 TWEAK_TEST(DumpAST);
 TEST_F(DumpASTTest, Test) {
   EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
Index: clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
@@ -0,0 +1,85 @@
+//===--- ObjcLocalizeStringLiteral.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 "Logger.h"
+#include "ParsedAST.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.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 {
+
+/// Wraps an Objective-C string literal with the NSLocalizedString macro.
+/// Before:
+///   @"description"
+///   ^^^
+/// After:
+///   NSLocalizedString(@"description", @"")
+class ObjCLocalizeStringLiteral : public Tweak {
+public:
+  const char *id() const override final;
+  Intent intent() const override { return Intent::Refactor; }
+
+  bool prepare(const Selection &Inputs) override;
+  Expected apply(const Selection &Inputs) override;
+  std::string title() const override;
+
+private:
+  const clang::ObjCStringLiteral *Str = nullptr;
+};
+
+REGISTER_TWEAK(ObjCLocalizeStringLiteral)
+
+bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {
+  const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
+  if (!N)
+return false;
+  // Allow the refactoring even if the user selected only the C string part
+  // of the expression.
+  if (N->ASTNode.get()) {
+if (N->Parent)
+  N = N->Parent;
+  }
+  Str = dyn_cast_or_null(N->ASTNode.get());
+  return Str;
+}
+
+Expected
+ObjCLocalizeStringLiteral::apply(const Selection &Inputs) {
+  auto &SM = Inputs.AST.getSourceManager();
+  auto &LangOpts = Inputs.AST.getASTContext().getLangOpts();
+  auto Reps = tooling::Replacements(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(Str->getBeginLoc()),
+  "NSLocalizedString(", LangOpts));
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+  Str->getEndLoc(), 0, Inputs.AST.getSourceManager(), LangOpts);
+  if (auto Err = Reps.add(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(EndLoc), ", @\"\")", LangOpts)))
+return std::move(Err);
+  return Effect::mainFileEdit(SM, std::move(Reps));
+}
+
+std::string ObjCLocalizeStringLiteral::title() const {
+  return "Wrap in NSLocalizedString";
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
===
--- clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
+++ clang-tools-ex

[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-12-04 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman marked 2 inline comments as done.
arphaman added inline comments.



Comment at: clang-tools-extra/clangd/ParsedAST.h:80
 
+  const LangOptions &getLangOpts() const {
+return getASTContext().getLangOpts();

kadircet wrote:
> arphaman wrote:
> > kadircet wrote:
> > > can we introduce this helper in a new patch, while changing other 
> > > occurrences in clangd?
> > Sounds good, I'll do that.
> can you also revert this change?
I precommited it in c0ee0224c4cf52bc6ba74dec88b30b850deca523


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543



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


[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-12-03 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet accepted this revision.
kadircet added a comment.
This revision is now accepted and ready to land.

Thanks, LGTM!




Comment at: clang-tools-extra/clangd/ParsedAST.h:80
 
+  const LangOptions &getLangOpts() const {
+return getASTContext().getLangOpts();

arphaman wrote:
> kadircet wrote:
> > can we introduce this helper in a new patch, while changing other 
> > occurrences in clangd?
> Sounds good, I'll do that.
can you also revert this change?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543



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


[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-12-02 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: clang-tools-extra/clangd/ParsedAST.h:80
 
+  const LangOptions &getLangOpts() const {
+return getASTContext().getLangOpts();

kadircet wrote:
> can we introduce this helper in a new patch, while changing other occurrences 
> in clangd?
Sounds good, I'll do that.



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp:34
+/// After:
+///   NSLocalizedString(@"description", "")
+class ObjCLocalizeStringLiteral : public Tweak {

kadircet wrote:
>  NSLocalizedString(@"description", `@`"")
Great catch, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543



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


[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-12-02 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 231799.
arphaman marked 6 inline comments as done.
arphaman added a comment.

Fixed nits.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543

Files:
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.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
@@ -122,6 +122,25 @@
   EXPECT_EQ(apply(Input), Output);
 }
 
+TWEAK_TEST(ObjCLocalizeStringLiteral);
+TEST_F(ObjCLocalizeStringLiteralTest, Test) {
+  ExtraArgs.push_back("-x");
+  ExtraArgs.push_back("objective-c");
+
+  // Ensure the the action can be initiated in the string literal.
+  EXPECT_AVAILABLE(R"(id x = ^[[@[[^"^t^est^";)");
+
+  // Ensure that the action can't be initiated in other places.
+  EXPECT_UNAVAILABLE(R"([[i^d ^[[x]] ^= @"test";^]])");
+
+  // Ensure that the action is not available for regular C strings.
+  EXPECT_UNAVAILABLE(R"(const char * x= "^test";)");
+
+  const char *Input = R"(id x = [[@"test"]];)";
+  const char *Output = R"(id x = NSLocalizedString(@"test", @"");)";
+  EXPECT_EQ(apply(Input), Output);
+}
+
 TWEAK_TEST(DumpAST);
 TEST_F(DumpASTTest, Test) {
   EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
Index: clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
@@ -0,0 +1,85 @@
+//===--- ObjcLocalizeStringLiteral.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 "Logger.h"
+#include "ParsedAST.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.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 {
+
+/// Wraps an Objective-C string literal with the NSLocalizedString macro.
+/// Before:
+///   @"description"
+///   ^^^
+/// After:
+///   NSLocalizedString(@"description", @"")
+class ObjCLocalizeStringLiteral : public Tweak {
+public:
+  const char *id() const override final;
+  Intent intent() const override { return Intent::Refactor; }
+
+  bool prepare(const Selection &Inputs) override;
+  Expected apply(const Selection &Inputs) override;
+  std::string title() const override;
+
+private:
+  const clang::ObjCStringLiteral *Str = nullptr;
+};
+
+REGISTER_TWEAK(ObjCLocalizeStringLiteral)
+
+bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {
+  const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
+  if (!N)
+return false;
+  // Allow the refactoring even if the user selected only the C string part
+  // of the expression.
+  if (N->ASTNode.get()) {
+if (N->Parent)
+  N = N->Parent;
+  }
+  Str = dyn_cast_or_null(N->ASTNode.get());
+  return Str;
+}
+
+Expected
+ObjCLocalizeStringLiteral::apply(const Selection &Inputs) {
+  auto &SM = Inputs.AST.getSourceManager();
+  auto &LangOpts = Inputs.AST.getASTContext().getLangOpts();
+  auto Reps = tooling::Replacements(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(Str->getBeginLoc()),
+  "NSLocalizedString(", LangOpts));
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+  Str->getEndLoc(), 0, Inputs.AST.getSourceManager(), LangOpts);
+  if (auto Err = Reps.add(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(EndLoc), ", @\"\")", LangOpts)))
+return std::move(Err);
+  return Effect::mainFileEdit(SM, std::move(Reps));
+}
+
+std::string ObjCLocalizeStringLiteral::title() const {
+  return "Wrap in NSLocalizedString";
+}
+
+} // namespace
+} // namespace clangd
+} // namespace clang
Index: clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
===
--- clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
+++ clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
@@ -19,6 +19,7 @@
   ExpandMacro.cpp
   ExtractFunction.cpp
   ExtractVariable.cpp
+  ObjCLocalizeStringLiteral.cpp
   Raw

[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-11-18 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added a comment.

implementation lgtm with a few nits.

main concern is about the new getlangopts helper




Comment at: clang-tools-extra/clangd/ParsedAST.h:80
 
+  const LangOptions &getLangOpts() const {
+return getASTContext().getLangOpts();

can we introduce this helper in a new patch, while changing other occurrences 
in clangd?



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp:34
+/// After:
+///   NSLocalizedString(@"description", "")
+class ObjCLocalizeStringLiteral : public Tweak {

 NSLocalizedString(@"description", `@`"")



Comment at: 
clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp:69
+  SM, CharSourceRange::getCharRange(Str->getBeginLoc()),
+  "NSLocalizedString(", Inputs.AST.getASTContext().getLangOpts()));
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(

maybe extract `Inputs.AST.getASTContext().getLangOpts()` into a variable and 
make use of it in the following places as well? (line 72 and 75)



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:131
+  // Ensure the the action can be initiated in the string literal.
+  EXPECT_AVAILABLE(R"(id x = ^@^"^t^est^";)");
+  EXPECT_AVAILABLE(R"(id x = [[@"test"]];)");

nit: you can combine all of this into a single test



Comment at: clang-tools-extra/clangd/unittests/TweakTests.cpp:136
+  // Ensure that the action can't be initiated in other places.
+  EXPECT_UNAVAILABLE(R"(i^d ^x ^= @"test";^)");
+  EXPECT_UNAVAILABLE(R"(id [[x]] = @"test";)");

nit: you can combine all of this into a single test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543



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


[PATCH] D69543: [clangd] Add a tweak refactoring to wrap Objective-C string literals in `NSLocalizedString` macros

2019-11-08 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman updated this revision to Diff 228548.
arphaman marked 2 inline comments as done.
arphaman retitled this revision from "[WIP][clangd] Add a tweak refactoring to 
wrap Objective-C string literals in `NSLocalizedString` macros" to "[clangd] 
Add a tweak refactoring to wrap Objective-C string literals in 
`NSLocalizedString` macros".
arphaman added a comment.

I figured out what I was doing wrong in the tests, and fixed them. This is no 
longer WIP and is ready for review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69543

Files:
  clang-tools-extra/clangd/ParsedAST.h
  clang-tools-extra/clangd/refactor/tweaks/CMakeLists.txt
  clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.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
@@ -122,6 +122,29 @@
   EXPECT_EQ(apply(Input), Output);
 }
 
+TWEAK_TEST(ObjCLocalizeStringLiteral);
+TEST_F(ObjCLocalizeStringLiteralTest, Test) {
+  ExtraArgs.push_back("-x");
+  ExtraArgs.push_back("objective-c");
+
+  // Ensure the the action can be initiated in the string literal.
+  EXPECT_AVAILABLE(R"(id x = ^@^"^t^est^";)");
+  EXPECT_AVAILABLE(R"(id x = [[@"test"]];)");
+  EXPECT_AVAILABLE(R"(id x = @[["test"]];)");
+
+  // Ensure that the action can't be initiated in other places.
+  EXPECT_UNAVAILABLE(R"(i^d ^x ^= @"test";^)");
+  EXPECT_UNAVAILABLE(R"(id [[x]] = @"test";)");
+  EXPECT_UNAVAILABLE(R"([[id x = @"test";]])");
+
+  // Ensure that the action is not available for regular C strings.
+  EXPECT_UNAVAILABLE(R"(const char * x= "^test";)");
+
+  const char *Input = R"(id x = [[@"test"]];)";
+  const char *Output = R"(id x = NSLocalizedString(@"test", @"");)";
+  EXPECT_EQ(apply(Input), Output);
+}
+
 TWEAK_TEST(DumpAST);
 TEST_F(DumpASTTest, Test) {
   EXPECT_AVAILABLE("^int f^oo() { re^turn 2 ^+ 2; }");
Index: clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
===
--- /dev/null
+++ clang-tools-extra/clangd/refactor/tweaks/ObjCLocalizeStringLiteral.cpp
@@ -0,0 +1,86 @@
+//===--- ObjcLocalizeStringLiteral.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 "Logger.h"
+#include "ParsedAST.h"
+#include "SourceCode.h"
+#include "refactor/Tweak.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.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 {
+
+/// Wraps an Objective-C string literal with the NSLocalizedString macro.
+/// Before:
+///   @"description"
+///   ^^^
+/// After:
+///   NSLocalizedString(@"description", "")
+class ObjCLocalizeStringLiteral : public Tweak {
+public:
+  const char *id() const override final;
+  Intent intent() const override { return Intent::Refactor; }
+
+  bool prepare(const Selection &Inputs) override;
+  Expected apply(const Selection &Inputs) override;
+  std::string title() const override;
+
+private:
+  const clang::ObjCStringLiteral *Str = nullptr;
+};
+
+REGISTER_TWEAK(ObjCLocalizeStringLiteral)
+
+bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {
+  const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
+  if (!N)
+return false;
+  // Allow the refactoring even if the user selected only the C string part
+  // of the expression.
+  if (N->ASTNode.get()) {
+if (N->Parent)
+  N = N->Parent;
+  }
+  Str = dyn_cast_or_null(N->ASTNode.get());
+  return Str;
+}
+
+Expected
+ObjCLocalizeStringLiteral::apply(const Selection &Inputs) {
+  auto &SM = Inputs.AST.getSourceManager();
+  auto Reps = tooling::Replacements(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(Str->getBeginLoc()),
+  "NSLocalizedString(", Inputs.AST.getASTContext().getLangOpts()));
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+  Str->getEndLoc(), 0, Inputs.AST.getSourceManager(),
+  Inputs.AST.getLangOpts());
+  if (auto Err = Reps.add(tooling::Replacement(
+  SM, CharSourceRange::getCharRange(EndLoc), ", @\"\")",
+  Inputs.AST.getASTContext().getLangOpts(
+return std::move(Err);
+  return Effect::mainFileE