brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.6 KiB · c513a18 Raw
86 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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/StringRef.h"17#include "llvm/Support/Casting.h"18#include "llvm/Support/Error.h"19 20namespace clang {21namespace clangd {22namespace {23 24/// Wraps an Objective-C string literal with the NSLocalizedString macro.25/// Before:26///   @"description"27///   ^^^28/// After:29///   NSLocalizedString(@"description", @"")30class ObjCLocalizeStringLiteral : public Tweak {31public:32  const char *id() const final;33  llvm::StringLiteral kind() const override {34    return CodeAction::REFACTOR_KIND;35  }36 37  bool prepare(const Selection &Inputs) override;38  Expected<Tweak::Effect> apply(const Selection &Inputs) override;39  std::string title() const override;40 41private:42  const clang::ObjCStringLiteral *Str = nullptr;43};44 45REGISTER_TWEAK(ObjCLocalizeStringLiteral)46 47bool ObjCLocalizeStringLiteral::prepare(const Selection &Inputs) {48  const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor();49  if (!N)50    return false;51  // Allow the refactoring even if the user selected only the C string part52  // of the expression.53  if (N->ASTNode.get<StringLiteral>()) {54    if (N->Parent)55      N = N->Parent;56  }57  Str = dyn_cast_or_null<ObjCStringLiteral>(N->ASTNode.get<Stmt>());58  return Str;59}60 61Expected<Tweak::Effect>62ObjCLocalizeStringLiteral::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));77}78 79std::string ObjCLocalizeStringLiteral::title() const {80  return "Wrap in NSLocalizedString";81}82 83} // namespace84} // namespace clangd85} // namespace clang86