1 //===--- ObjcLocalizeStringLiteral.cpp ---------------------------*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
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/StringRef.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/Error.h"
24 /// Wraps an Objective-C string literal with the NSLocalizedString macro.
29 /// NSLocalizedString(@"description", @"")
30 class ObjCLocalizeStringLiteral
: public Tweak
{
32 const char *id() const final
;
33 llvm::StringLiteral
kind() const override
{
34 return CodeAction::REFACTOR_KIND
;
37 bool prepare(const Selection
&Inputs
) override
;
38 Expected
<Tweak::Effect
> apply(const Selection
&Inputs
) override
;
39 std::string
title() const override
;
42 const clang::ObjCStringLiteral
*Str
= nullptr;
45 REGISTER_TWEAK(ObjCLocalizeStringLiteral
)
47 bool ObjCLocalizeStringLiteral::prepare(const Selection
&Inputs
) {
48 const SelectionTree::Node
*N
= Inputs
.ASTSelection
.commonAncestor();
51 // Allow the refactoring even if the user selected only the C string part
53 if (N
->ASTNode
.get
<StringLiteral
>()) {
57 Str
= dyn_cast_or_null
<ObjCStringLiteral
>(N
->ASTNode
.get
<Stmt
>());
61 Expected
<Tweak::Effect
>
62 ObjCLocalizeStringLiteral::apply(const Selection
&Inputs
) {
63 auto *AST
= Inputs
.AST
;
64 auto &SM
= AST
->getSourceManager();
65 const auto &TB
= AST
->getTokens();
66 auto Toks
= TB
.spelledForExpanded(TB
.expandedTokens(Str
->getSourceRange()));
67 if (!Toks
|| Toks
->empty())
68 return error("Failed to find tokens to replace.");
69 // Insert `NSLocalizedString(` before the literal.
70 auto Reps
= tooling::Replacements(tooling::Replacement(
71 SM
, Toks
->front().location(), 0, "NSLocalizedString("));
72 // Insert `, @"")` after the literal.
73 if (auto Err
= Reps
.add(
74 tooling::Replacement(SM
, Toks
->back().endLocation(), 0, ", @\"\")")))
75 return std::move(Err
);
76 return Effect::mainFileEdit(SM
, std::move(Reps
));
79 std::string
ObjCLocalizeStringLiteral::title() const {
80 return "Wrap in NSLocalizedString";