clang-tools  14.0.0git
ObjCLocalizeStringLiteral.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
8 
9 #include "ParsedAST.h"
10 #include "SourceCode.h"
11 #include "refactor/Tweak.h"
12 #include "support/Logger.h"
13 #include "clang/AST/ExprObjC.h"
14 #include "clang/Basic/LangOptions.h"
15 #include "clang/Basic/SourceLocation.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Tooling/Core/Replacement.h"
18 #include "llvm/ADT/None.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/iterator_range.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Error.h"
24 
25 namespace clang {
26 namespace clangd {
27 namespace {
28 
29 /// Wraps an Objective-C string literal with the NSLocalizedString macro.
30 /// Before:
31 /// @"description"
32 /// ^^^
33 /// After:
34 /// NSLocalizedString(@"description", @"")
35 class ObjCLocalizeStringLiteral : public Tweak {
36 public:
37  const char *id() const override final;
38  llvm::StringLiteral kind() const override {
40  }
41 
42  bool prepare(const Selection &Inputs) override;
43  Expected<Tweak::Effect> apply(const Selection &Inputs) override;
44  std::string title() const override;
45 
46 private:
47  const clang::ObjCStringLiteral *Str = nullptr;
48 };
49 
50 REGISTER_TWEAK(ObjCLocalizeStringLiteral)
51 
52 bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {
53  const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();
54  if (!N)
55  return false;
56  // Allow the refactoring even if the user selected only the C string part
57  // of the expression.
58  if (N->ASTNode.get<StringLiteral>()) {
59  if (N->Parent)
60  N = N->Parent;
61  }
62  Str = dyn_cast_or_null<ObjCStringLiteral>(N->ASTNode.get<Stmt>());
63  return Str;
64 }
65 
66 Expected<Tweak::Effect>
67 ObjCLocalizeStringLiteral::apply(const Selection &Inputs) {
68  auto *AST = Inputs.AST;
69  auto &SM = AST->getSourceManager();
70  const auto &TB = AST->getTokens();
71  auto Toks = TB.spelledForExpanded(TB.expandedTokens(Str->getSourceRange()));
72  if (!Toks || Toks->empty())
73  return error("Failed to find tokens to replace.");
74  // Insert `NSLocalizedString(` before the literal.
75  auto Reps = tooling::Replacements(tooling::Replacement(
76  SM, Toks->front().location(), 0, "NSLocalizedString("));
77  // Insert `, @"")` after the literal.
78  if (auto Err = Reps.add(
79  tooling::Replacement(SM, Toks->back().endLocation(), 0, ", @\"\")")))
80  return std::move(Err);
81  return Effect::mainFileEdit(SM, std::move(Reps));
82 }
83 
84 std::string ObjCLocalizeStringLiteral::title() const {
85  return "Wrap in NSLocalizedString";
86 }
87 
88 } // namespace
89 } // namespace clangd
90 } // namespace clang
llvm
Some operations such as code completion produce a set of candidates.
Definition: YAMLGenerator.cpp:28
clang::clangd::error
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
Definition: Logger.h:80
Inputs
ParseInputs Inputs
Definition: TUScheduler.cpp:451
Tweak.h
Logger.h
SourceCode.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:108
clang::clangd::CodeAction::REFACTOR_KIND
const static llvm::StringLiteral REFACTOR_KIND
Definition: Protocol.h:980
SM
const SourceManager & SM
Definition: IncludeCleaner.cpp:108
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:75
REGISTER_TWEAK
#define REGISTER_TWEAK(Subclass)
Definition: Tweak.h:132
ParsedAST.h