[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / refactor / tweaks / ObjCLocalizeStringLiteral.cpp
blob62995840ac24a5aa0436bd8892868e2506319467
1 //===--- ObjcLocalizeStringLiteral.cpp ---------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "ParsedAST.h"
10 #include "refactor/Tweak.h"
11 #include "support/Logger.h"
12 #include "clang/AST/ExprObjC.h"
13 #include "clang/Basic/SourceLocation.h"
14 #include "clang/Basic/SourceManager.h"
15 #include "clang/Tooling/Core/Replacement.h"
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Casting.h"
19 #include "llvm/Support/Error.h"
21 namespace clang {
22 namespace clangd {
23 namespace {
25 /// Wraps an Objective-C string literal with the NSLocalizedString macro.
26 /// Before:
27 /// @"description"
28 /// ^^^
29 /// After:
30 /// NSLocalizedString(@"description", @"")
31 class ObjCLocalizeStringLiteral : public Tweak {
32 public:
33 const char *id() const final;
34 llvm::StringLiteral kind() const override {
35 return CodeAction::REFACTOR_KIND;
38 bool prepare(const Selection &Inputs) override;
39 Expected<Tweak::Effect> apply(const Selection &Inputs) override;
40 std::string title() const override;
42 private:
43 const clang::ObjCStringLiteral *Str = nullptr;
46 REGISTER_TWEAK(ObjCLocalizeStringLiteral)
48 bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {
49 const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
50 if (!N)
51 return false;
52 // Allow the refactoring even if the user selected only the C string part
53 // of the expression.
54 if (N->ASTNode.get<StringLiteral>()) {
55 if (N->Parent)
56 N = N->Parent;
58 Str = dyn_cast_or_null<ObjCStringLiteral>(N->ASTNode.get<Stmt>());
59 return Str;
62 Expected<Tweak::Effect>
63 ObjCLocalizeStringLiteral::apply(const Selection &Inputs) {
64 auto *AST = Inputs.AST;
65 auto &SM = AST->getSourceManager();
66 const auto &TB = AST->getTokens();
67 auto Toks = TB.spelledForExpanded(TB.expandedTokens(Str->getSourceRange()));
68 if (!Toks || Toks->empty())
69 return error("Failed to find tokens to replace.");
70 // Insert `NSLocalizedString(` before the literal.
71 auto Reps = tooling::Replacements(tooling::Replacement(
72 SM, Toks->front().location(), 0, "NSLocalizedString("));
73 // Insert `, @"")` after the literal.
74 if (auto Err = Reps.add(
75 tooling::Replacement(SM, Toks->back().endLocation(), 0, ", @\"\")")))
76 return std::move(Err);
77 return Effect::mainFileEdit(SM, std::move(Reps));
80 std::string ObjCLocalizeStringLiteral::title() const {
81 return "Wrap in NSLocalizedString";
84 } // namespace
85 } // namespace clangd
86 } // namespace clang