r374271 - [libTooling] Move Transformer files to their own directory/library.

Yitzhak Mandelbaum via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 9 19:34:47 PDT 2019


Author: ymandel
Date: Wed Oct  9 19:34:47 2019
New Revision: 374271

URL: http://llvm.org/viewvc/llvm-project?rev=374271&view=rev
Log:
[libTooling] Move Transformer files to their own directory/library.

Summary:
The Transformer library has been growing inside of
lib/Tooling/Refactoring. However, it's not really related to anything else in
that directory. This revision moves all Transformer-related files into their own
include & lib directories.  A followup revision will (temporarily) add
forwarding headers to help any users migrate their code to the new location.

Reviewers: gribozavr

Subscribers: mgorny, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D68637

Added:
    cfe/trunk/include/clang/Tooling/Transformer/
    cfe/trunk/include/clang/Tooling/Transformer/MatchConsumer.h
    cfe/trunk/include/clang/Tooling/Transformer/RangeSelector.h
    cfe/trunk/include/clang/Tooling/Transformer/SourceCode.h
    cfe/trunk/include/clang/Tooling/Transformer/SourceCodeBuilders.h
    cfe/trunk/include/clang/Tooling/Transformer/Stencil.h
    cfe/trunk/include/clang/Tooling/Transformer/Transformer.h
    cfe/trunk/lib/Tooling/Transformer/
    cfe/trunk/lib/Tooling/Transformer/CMakeLists.txt
    cfe/trunk/lib/Tooling/Transformer/RangeSelector.cpp
    cfe/trunk/lib/Tooling/Transformer/SourceCode.cpp
    cfe/trunk/lib/Tooling/Transformer/SourceCodeBuilders.cpp
    cfe/trunk/lib/Tooling/Transformer/Stencil.cpp
    cfe/trunk/lib/Tooling/Transformer/Transformer.cpp
Removed:
    cfe/trunk/include/clang/Tooling/Refactoring/MatchConsumer.h
    cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h
    cfe/trunk/include/clang/Tooling/Refactoring/SourceCode.h
    cfe/trunk/include/clang/Tooling/Refactoring/SourceCodeBuilders.h
    cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h
    cfe/trunk/include/clang/Tooling/Refactoring/Transformer.h
    cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp
    cfe/trunk/lib/Tooling/Refactoring/SourceCode.cpp
    cfe/trunk/lib/Tooling/Refactoring/SourceCodeBuilders.cpp
    cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp
    cfe/trunk/lib/Tooling/Refactoring/Transformer.cpp
Modified:
    cfe/trunk/lib/Tooling/CMakeLists.txt
    cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt
    cfe/trunk/unittests/Tooling/CMakeLists.txt
    cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp
    cfe/trunk/unittests/Tooling/SourceCodeBuildersTest.cpp
    cfe/trunk/unittests/Tooling/SourceCodeTest.cpp
    cfe/trunk/unittests/Tooling/StencilTest.cpp
    cfe/trunk/unittests/Tooling/TransformerTest.cpp

Removed: cfe/trunk/include/clang/Tooling/Refactoring/MatchConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/MatchConsumer.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/MatchConsumer.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/MatchConsumer.h (removed)
@@ -1,58 +0,0 @@
-//===--- MatchConsumer.h - MatchConsumer abstraction ------------*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file This file defines the *MatchConsumer* abstraction: a computation over
-/// match results, specifically the `ast_matchers::MatchFinder::MatchResult`
-/// class.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_MATCH_CONSUMER_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_MATCH_CONSUMER_H_
-
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-
-namespace clang {
-namespace tooling {
-
-/// A failable computation over nodes bound by AST matchers.
-///
-/// The computation should report any errors though its return value (rather
-/// than terminating the program) to enable usage in interactive scenarios like
-/// clang-query.
-///
-/// This is a central abstraction of the Transformer framework.
-template <typename T>
-using MatchConsumer =
-    std::function<Expected<T>(const ast_matchers::MatchFinder::MatchResult &)>;
-
-/// Creates an error that signals that a `MatchConsumer` expected a certain node
-/// to be bound by AST matchers, but it was not actually bound.
-inline llvm::Error notBoundError(llvm::StringRef Id) {
-  return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
-                                             "Id not bound: " + Id);
-}
-
-/// Chooses between the two consumers, based on whether \p ID is bound in the
-/// match.
-template <typename T>
-MatchConsumer<T> ifBound(std::string ID, MatchConsumer<T> TrueC,
-                         MatchConsumer<T> FalseC) {
-  return [=](const ast_matchers::MatchFinder::MatchResult &Result) {
-    auto &Map = Result.Nodes.getMap();
-    return (Map.find(ID) != Map.end() ? TrueC : FalseC)(Result);
-  };
-}
-
-} // namespace tooling
-} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_MATCH_CONSUMER_H_

Removed: cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/RangeSelector.h (removed)
@@ -1,93 +0,0 @@
-//===--- RangeSelector.h - Source-selection library ---------*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-///  \file
-///  Defines a combinator library supporting the definition of _selectors_,
-///  which select source ranges based on (bound) AST nodes.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_
-
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Tooling/Refactoring/MatchConsumer.h"
-#include "llvm/Support/Error.h"
-#include <functional>
-#include <string>
-
-namespace clang {
-namespace tooling {
-using RangeSelector = MatchConsumer<CharSourceRange>;
-
-inline RangeSelector charRange(CharSourceRange R) {
-  return [R](const ast_matchers::MatchFinder::MatchResult &)
-             -> Expected<CharSourceRange> { return R; };
-}
-
-/// Selects from the start of \p Begin and to the end of \p End.
-RangeSelector range(RangeSelector Begin, RangeSelector End);
-
-/// Convenience version of \c range where end-points are bound nodes.
-RangeSelector range(std::string BeginID, std::string EndID);
-
-/// Selects the (empty) range [B,B) when \p Selector selects the range [B,E).
-RangeSelector before(RangeSelector Selector);
-
-/// Selects the the point immediately following \p Selector. That is, the
-/// (empty) range [E,E), when \p Selector selects either
-/// * the CharRange [B,E) or
-/// * the TokenRange [B,E'] where the token at E' spans the range [E,E').
-RangeSelector after(RangeSelector Selector);
-
-/// Selects a node, including trailing semicolon (for non-expression
-/// statements). \p ID is the node's binding in the match result.
-RangeSelector node(std::string ID);
-
-/// Selects a node, including trailing semicolon (always). Useful for selecting
-/// expression statements. \p ID is the node's binding in the match result.
-RangeSelector statement(std::string ID);
-
-/// Given a \c MemberExpr, selects the member token. \p ID is the node's
-/// binding in the match result.
-RangeSelector member(std::string ID);
-
-/// Given a node with a "name", (like \c NamedDecl, \c DeclRefExpr or \c
-/// CxxCtorInitializer) selects the name's token.  Only selects the final
-/// identifier of a qualified name, but not any qualifiers or template
-/// arguments.  For example, for `::foo::bar::baz` and `::foo::bar::baz<int>`,
-/// it selects only `baz`.
-///
-/// \param ID is the node's binding in the match result.
-RangeSelector name(std::string ID);
-
-// Given a \c CallExpr (bound to \p ID), selects the arguments' source text (all
-// source between the call's parentheses).
-RangeSelector callArgs(std::string ID);
-
-// Given a \c CompoundStmt (bound to \p ID), selects the source of the
-// statements (all source between the braces).
-RangeSelector statements(std::string ID);
-
-// Given a \c InitListExpr (bound to \p ID), selects the range of the elements
-// (all source between the braces).
-RangeSelector initListElements(std::string ID);
-
-/// Given an \IfStmt (bound to \p ID), selects the range of the else branch,
-/// starting from the \c else keyword.
-RangeSelector elseBranch(std::string ID);
-
-/// Selects the range from which `S` was expanded (possibly along with other
-/// source), if `S` is an expansion, and `S` itself, otherwise.  Corresponds to
-/// `SourceManager::getExpansionRange`.
-RangeSelector expansion(RangeSelector S);
-} // namespace tooling
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_

Removed: cfe/trunk/include/clang/Tooling/Refactoring/SourceCode.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/SourceCode.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/SourceCode.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/SourceCode.h (removed)
@@ -1,90 +0,0 @@
-//===--- SourceCode.h - Source code manipulation routines -------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file provides functions that simplify extraction of source code.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H
-#define LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/TokenKinds.h"
-
-namespace clang {
-namespace tooling {
-
-/// Extends \p Range to include the token \p Next, if it immediately follows the
-/// end of the range. Otherwise, returns \p Range unchanged.
-CharSourceRange maybeExtendRange(CharSourceRange Range, tok::TokenKind Next,
-                                 ASTContext &Context);
-
-/// Returns the source range spanning the node, extended to include \p Next, if
-/// it immediately follows \p Node. Otherwise, returns the normal range of \p
-/// Node.  See comments on `getExtendedText()` for examples.
-template <typename T>
-CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next,
-                                 ASTContext &Context) {
-  return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()),
-                          Next, Context);
-}
-
-/// Returns the source-code text in the specified range.
-StringRef getText(CharSourceRange Range, const ASTContext &Context);
-
-/// Returns the source-code text corresponding to \p Node.
-template <typename T>
-StringRef getText(const T &Node, const ASTContext &Context) {
-  return getText(CharSourceRange::getTokenRange(Node.getSourceRange()),
-                 Context);
-}
-
-/// Returns the source text of the node, extended to include \p Next, if it
-/// immediately follows the node. Otherwise, returns the text of just \p Node.
-///
-/// For example, given statements S1 and S2 below:
-/// \code
-///   {
-///     // S1:
-///     if (!x) return foo();
-///     // S2:
-///     if (!x) { return 3; }
-///   }
-/// \endcode
-/// then
-/// \code
-///   getText(S1, Context) = "if (!x) return foo()"
-///   getExtendedText(S1, tok::TokenKind::semi, Context)
-///     = "if (!x) return foo();"
-///   getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context)
-///     = "return foo();"
-///   getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context)
-///     = getText(S2, Context) = "{ return 3; }"
-/// \endcode
-template <typename T>
-StringRef getExtendedText(const T &Node, tok::TokenKind Next,
-                          ASTContext &Context) {
-  return getText(getExtendedRange(Node, Next, Context), Context);
-}
-
-// Attempts to resolve the given range to one that can be edited by a rewrite;
-// generally, one that starts and ends within a particular file. It supports
-// a limited set of cases involving source locations in macro expansions.
-llvm::Optional<CharSourceRange>
-getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM,
-                const LangOptions &LangOpts);
-
-inline llvm::Optional<CharSourceRange>
-getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) {
-  return getRangeForEdit(EditRange, Context.getSourceManager(),
-                         Context.getLangOpts());
-}
-} // namespace tooling
-} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_H

Removed: cfe/trunk/include/clang/Tooling/Refactoring/SourceCodeBuilders.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/SourceCodeBuilders.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/SourceCodeBuilders.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/SourceCodeBuilders.h (removed)
@@ -1,86 +0,0 @@
-//===--- SourceCodeBuilders.h - Source-code building facilities -*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file collects facilities for generating source code strings.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_BUILDERS_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_BUILDERS_H_
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include <string>
-
-namespace clang {
-namespace tooling {
-
-/// \name Code analysis utilities.
-/// @{
-/// Ignores implicit object-construction expressions in addition to the normal
-/// implicit expressions that are ignored.
-const Expr *reallyIgnoreImplicit(const Expr &E);
-
-/// Determines whether printing this expression in *any* expression requires
-/// parentheses to preserve its meaning. This analyses is necessarily
-/// conservative because it lacks information about the target context.
-bool mayEverNeedParens(const Expr &E);
-
-/// Determines whether printing this expression to the left of a dot or arrow
-/// operator requires a parentheses to preserve its meaning. Given that
-/// dot/arrow are (effectively) the highest precedence, this is equivalent to
-/// asking whether it ever needs parens.
-inline bool needParensBeforeDotOrArrow(const Expr &E) {
-  return mayEverNeedParens(E);
-}
-
-/// Determines whether printing this expression to the right of a unary operator
-/// requires a parentheses to preserve its meaning.
-bool needParensAfterUnaryOperator(const Expr &E);
-/// @}
-
-/// \name Basic code-string generation utilities.
-/// @{
-
-/// Builds source for an expression, adding parens if needed for unambiguous
-/// parsing.
-llvm::Optional<std::string> buildParens(const Expr &E,
-                                        const ASTContext &Context);
-
-/// Builds idiomatic source for the dereferencing of `E`: prefix with `*` but
-/// simplify when it already begins with `&`.  \returns empty string on failure.
-llvm::Optional<std::string> buildDereference(const Expr &E,
-                                             const ASTContext &Context);
-
-/// Builds idiomatic source for taking the address of `E`: prefix with `&` but
-/// simplify when it already begins with `*`.  \returns empty string on failure.
-llvm::Optional<std::string> buildAddressOf(const Expr &E,
-                                           const ASTContext &Context);
-
-/// Adds a dot to the end of the given expression, but adds parentheses when
-/// needed by the syntax, and simplifies to `->` when possible, e.g.:
-///
-///  `x` becomes `x.`
-///  `*a` becomes `a->`
-///  `a+b` becomes `(a+b).`
-llvm::Optional<std::string> buildDot(const Expr &E, const ASTContext &Context);
-
-/// Adds an arrow to the end of the given expression, but adds parentheses
-/// when needed by the syntax, and simplifies to `.` when possible, e.g.:
-///
-///  `x` becomes `x->`
-///  `&a` becomes `a.`
-///  `a+b` becomes `(a+b)->`
-llvm::Optional<std::string> buildArrow(const Expr &E,
-                                       const ASTContext &Context);
-/// @}
-
-} // namespace tooling
-} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_SOURCE_CODE_BUILDERS_H_

Removed: cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/Stencil.h (removed)
@@ -1,226 +0,0 @@
-//===--- Stencil.h - Stencil class ------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file defines the *Stencil* abstraction: a code-generating object,
-/// parameterized by named references to (bound) AST nodes.  Given a match
-/// result, a stencil can be evaluated to a string of source code.
-///
-/// A stencil is similar in spirit to a format string: it is composed of a
-/// series of raw text strings, references to nodes (the parameters) and helper
-/// code-generation operations.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Tooling/Refactoring/MatchConsumer.h"
-#include "clang/Tooling/Refactoring/RangeSelector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include <string>
-#include <vector>
-
-namespace clang {
-namespace tooling {
-
-/// A stencil is represented as a sequence of "parts" that can each individually
-/// generate a code string based on a match result.  The different kinds of
-/// parts include (raw) text, references to bound nodes and assorted operations
-/// on bound nodes.
-///
-/// Users can create custom Stencil operations by implementing this interface.
-class StencilPartInterface {
-public:
-  virtual ~StencilPartInterface() = default;
-
-  /// Evaluates this part to a string and appends it to \c Result.  \c Result is
-  /// undefined in the case of an error.
-  virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
-                           std::string *Result) const = 0;
-
-  virtual bool isEqual(const StencilPartInterface &other) const = 0;
-
-  /// Constructs a string representation of the StencilPart. StencilParts
-  /// generated by the `selection` and `run` functions do not have a unique
-  /// string representation.
-  virtual std::string toString() const = 0;
-
-  const void *typeId() const { return TypeId; }
-
-protected:
-  StencilPartInterface(const void *DerivedId) : TypeId(DerivedId) {}
-
-  // Since this is an abstract class, copying/assigning only make sense for
-  // derived classes implementing `clone()`.
-  StencilPartInterface(const StencilPartInterface &) = default;
-  StencilPartInterface &operator=(const StencilPartInterface &) = default;
-
-  /// Unique identifier of the concrete type of this instance.  Supports safe
-  /// downcasting.
-  const void *TypeId;
-};
-
-/// A copyable facade for a std::unique_ptr<StencilPartInterface>. Copies result
-/// in a copy of the underlying pointee object.
-class StencilPart {
-public:
-  explicit StencilPart(std::shared_ptr<StencilPartInterface> Impl)
-      : Impl(std::move(Impl)) {}
-
-  /// See `StencilPartInterface::eval()`.
-  llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
-                   std::string *Result) const {
-    return Impl->eval(Match, Result);
-  }
-
-  bool operator==(const StencilPart &Other) const {
-    if (Impl == Other.Impl)
-      return true;
-    if (Impl == nullptr || Other.Impl == nullptr)
-      return false;
-    return Impl->isEqual(*Other.Impl);
-  }
-
-  std::string toString() const {
-    if (Impl == nullptr)
-      return "";
-    return Impl->toString();
-  }
-
-private:
-  std::shared_ptr<StencilPartInterface> Impl;
-};
-
-/// A sequence of code fragments, references to parameters and code-generation
-/// operations that together can be evaluated to (a fragment of) source code,
-/// given a match result.
-class Stencil {
-public:
-  Stencil() = default;
-
-  /// Composes a stencil from a series of parts.
-  template <typename... Ts> static Stencil cat(Ts &&... Parts) {
-    Stencil S;
-    S.Parts = {wrap(std::forward<Ts>(Parts))...};
-    return S;
-  }
-
-  /// Appends data from a \p OtherStencil to this stencil.
-  void append(Stencil OtherStencil);
-
-  // Evaluates the stencil given a match result. Requires that the nodes in the
-  // result includes any ids referenced in the stencil. References to missing
-  // nodes will result in an invalid_argument error.
-  llvm::Expected<std::string>
-  eval(const ast_matchers::MatchFinder::MatchResult &Match) const;
-
-  // Allow Stencils to operate as std::function, for compatibility with
-  // Transformer's TextGenerator.
-  llvm::Expected<std::string>
-  operator()(const ast_matchers::MatchFinder::MatchResult &Result) const {
-    return eval(Result);
-  }
-
-  /// Constructs a string representation of the Stencil. The string is not
-  /// guaranteed to be unique.
-  std::string toString() const {
-    std::vector<std::string> PartStrings;
-    PartStrings.reserve(Parts.size());
-    for (const auto &Part : Parts)
-      PartStrings.push_back(Part.toString());
-    return llvm::join(PartStrings, ", ");
-  }
-
-private:
-  friend bool operator==(const Stencil &A, const Stencil &B);
-  static StencilPart wrap(llvm::StringRef Text);
-  static StencilPart wrap(RangeSelector Selector);
-  static StencilPart wrap(StencilPart Part) { return Part; }
-
-  std::vector<StencilPart> Parts;
-};
-
-inline bool operator==(const Stencil &A, const Stencil &B) {
-  return A.Parts == B.Parts;
-}
-
-inline bool operator!=(const Stencil &A, const Stencil &B) { return !(A == B); }
-
-// Functions for conveniently building stencils.
-namespace stencil {
-/// Convenience wrapper for Stencil::cat that can be imported with a using decl.
-template <typename... Ts> Stencil cat(Ts &&... Parts) {
-  return Stencil::cat(std::forward<Ts>(Parts)...);
-}
-
-/// \returns exactly the text provided.
-StencilPart text(llvm::StringRef Text);
-
-/// \returns the source corresponding to the selected range.
-StencilPart selection(RangeSelector Selector);
-
-/// \returns the source corresponding to the identified node.
-/// FIXME: Deprecated. Write `selection(node(Id))` instead.
-inline StencilPart node(llvm::StringRef Id) {
-  return selection(tooling::node(Id));
-}
-
-/// Generates the source of the expression bound to \p Id, wrapping it in
-/// parentheses if it may parse differently depending on context. For example, a
-/// binary operation is always wrapped, while a variable reference is never
-/// wrapped.
-StencilPart expression(llvm::StringRef Id);
-
-/// Constructs an idiomatic dereferencing of the expression bound to \p ExprId.
-/// \p ExprId is wrapped in parentheses, if needed.
-StencilPart deref(llvm::StringRef ExprId);
-
-/// Constructs an expression that idiomatically takes the address of the
-/// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if
-/// needed.
-StencilPart addressOf(llvm::StringRef ExprId);
-
-/// Constructs a `MemberExpr` that accesses the named member (\p Member) of the
-/// object bound to \p BaseId. The access is constructed idiomatically: if \p
-/// BaseId is bound to `e` and \p Member identifies member `m`, then returns
-/// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise.
-/// Additionally, `e` is wrapped in parentheses, if needed.
-StencilPart access(llvm::StringRef BaseId, StencilPart Member);
-inline StencilPart access(llvm::StringRef BaseId, llvm::StringRef Member) {
-  return access(BaseId, text(Member));
-}
-
-/// Chooses between the two stencil parts, based on whether \p ID is bound in
-/// the match.
-StencilPart ifBound(llvm::StringRef Id, StencilPart TruePart,
-                    StencilPart FalsePart);
-
-/// Chooses between the two strings, based on whether \p ID is bound in the
-/// match.
-inline StencilPart ifBound(llvm::StringRef Id, llvm::StringRef TrueText,
-                           llvm::StringRef FalseText) {
-  return ifBound(Id, text(TrueText), text(FalseText));
-}
-
-/// Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
-/// This supports user-defined extensions to the Stencil language.
-StencilPart run(MatchConsumer<std::string> C);
-
-/// For debug use only; semantics are not guaranteed.
-///
-/// \returns the string resulting from calling the node's print() method.
-StencilPart dPrint(llvm::StringRef Id);
-} // namespace stencil
-} // namespace tooling
-} // namespace clang
-#endif // LLVM_CLANG_TOOLING_REFACTOR_STENCIL_H_

Removed: cfe/trunk/include/clang/Tooling/Refactoring/Transformer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Refactoring/Transformer.h?rev=374270&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Refactoring/Transformer.h (original)
+++ cfe/trunk/include/clang/Tooling/Refactoring/Transformer.h (removed)
@@ -1,320 +0,0 @@
-//===--- Transformer.h - Clang source-rewriting library ---------*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-///  \file
-///  Defines a library supporting the concise specification of clang-based
-///  source-to-source transformations.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_
-#define LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_
-
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/ASTMatchers/ASTMatchersInternal.h"
-#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "clang/Tooling/Refactoring/MatchConsumer.h"
-#include "clang/Tooling/Refactoring/RangeSelector.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Error.h"
-#include <deque>
-#include <functional>
-#include <string>
-#include <type_traits>
-#include <utility>
-
-namespace clang {
-namespace tooling {
-
-using TextGenerator = MatchConsumer<std::string>;
-
-/// Wraps a string as a TextGenerator.
-inline TextGenerator text(std::string M) {
-  return [M](const ast_matchers::MatchFinder::MatchResult &)
-             -> Expected<std::string> { return M; };
-}
-
-// Description of a source-code edit, expressed in terms of an AST node.
-// Includes: an ID for the (bound) node, a selector for source related to the
-// node, a replacement and, optionally, an explanation for the edit.
-//
-// * Target: the source code impacted by the rule. This identifies an AST node,
-//   or part thereof (\c Part), whose source range indicates the extent of the
-//   replacement applied by the replacement term.  By default, the extent is the
-//   node matched by the pattern term (\c NodePart::Node). Target's are typed
-//   (\c Kind), which guides the determination of the node extent.
-//
-// * Replacement: a function that produces a replacement string for the target,
-//   based on the match result.
-//
-// * Note: (optional) a note specifically for this edit, potentially referencing
-//   elements of the match.  This will be displayed to the user, where possible;
-//   for example, in clang-tidy diagnostics.  Use of notes should be rare --
-//   explanations of the entire rewrite should be set in the rule
-//   (`RewriteRule::Explanation`) instead.  Notes serve the rare cases wherein
-//   edit-specific diagnostics are required.
-//
-// `ASTEdit` should be built using the `change` convenience functions. For
-// example,
-// \code
-//   change(name(fun), text("Frodo"))
-// \endcode
-// Or, if we use Stencil for the TextGenerator:
-// \code
-//   using stencil::cat;
-//   change(statement(thenNode), cat("{", thenNode, "}"))
-//   change(callArgs(call), cat(x, ",", y))
-// \endcode
-// Or, if you are changing the node corresponding to the rule's matcher, you can
-// use the single-argument override of \c change:
-// \code
-//   change(cat("different_expr"))
-// \endcode
-struct ASTEdit {
-  RangeSelector TargetRange;
-  TextGenerator Replacement;
-  TextGenerator Note;
-};
-
-/// Format of the path in an include directive -- angle brackets or quotes.
-enum class IncludeFormat {
-  Quoted,
-  Angled,
-};
-
-/// Description of a source-code transformation.
-//
-// A *rewrite rule* describes a transformation of source code. A simple rule
-// contains each of the following components:
-//
-// * Matcher: the pattern term, expressed as clang matchers (with Transformer
-//   extensions).
-//
-// * Edits: a set of Edits to the source code, described with ASTEdits.
-//
-// * Explanation: explanation of the rewrite.  This will be displayed to the
-//   user, where possible; for example, in clang-tidy diagnostics.
-//
-// However, rules can also consist of (sub)rules, where the first that matches
-// is applied and the rest are ignored.  So, the above components are gathered
-// as a `Case` and a rule is a list of cases.
-//
-// Rule cases have an additional, implicit, component: the parameters. These are
-// portions of the pattern which are left unspecified, yet bound in the pattern
-// so that we can reference them in the edits.
-//
-// The \c Transformer class can be used to apply the rewrite rule and obtain the
-// corresponding replacements.
-struct RewriteRule {
-  struct Case {
-    ast_matchers::internal::DynTypedMatcher Matcher;
-    SmallVector<ASTEdit, 1> Edits;
-    TextGenerator Explanation;
-    // Include paths to add to the file affected by this case.  These are
-    // bundled with the `Case`, rather than the `RewriteRule`, because each case
-    // might have different associated changes to the includes.
-    std::vector<std::pair<std::string, IncludeFormat>> AddedIncludes;
-  };
-  // We expect RewriteRules will most commonly include only one case.
-  SmallVector<Case, 1> Cases;
-
-  // ID used as the default target of each match. The node described by the
-  // matcher is should always be bound to this id.
-  static constexpr llvm::StringLiteral RootID = "___root___";
-};
-
-/// Convenience function for constructing a simple \c RewriteRule.
-RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
-                     SmallVector<ASTEdit, 1> Edits,
-                     TextGenerator Explanation = nullptr);
-
-/// Convenience overload of \c makeRule for common case of only one edit.
-inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
-                            ASTEdit Edit,
-                            TextGenerator Explanation = nullptr) {
-  SmallVector<ASTEdit, 1> Edits;
-  Edits.emplace_back(std::move(Edit));
-  return makeRule(std::move(M), std::move(Edits), std::move(Explanation));
-}
-
-/// For every case in Rule, adds an include directive for the given header. The
-/// common use is assumed to be a rule with only one case. For example, to
-/// replace a function call and add headers corresponding to the new code, one
-/// could write:
-/// \code
-///   auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))),
-///            change(text("bar()")));
-///   AddInclude(R, "path/to/bar_header.h");
-///   AddInclude(R, "vector", IncludeFormat::Angled);
-/// \endcode
-void addInclude(RewriteRule &Rule, llvm::StringRef Header,
-                IncludeFormat Format = IncludeFormat::Quoted);
-
-/// Applies the first rule whose pattern matches; other rules are ignored.  If
-/// the matchers are independent then order doesn't matter. In that case,
-/// `applyFirst` is simply joining the set of rules into one.
-//
-// `applyFirst` is like an `anyOf` matcher with an edit action attached to each
-// of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and
-// then dispatch on those ids in your code for control flow, `applyFirst` lifts
-// that behavior to the rule level.  So, you can write `applyFirst({makeRule(m1,
-// action1), makeRule(m2, action2), ...});`
-//
-// For example, consider a type `T` with a deterministic serialization function,
-// `serialize()`.  For performance reasons, we would like to make it
-// non-deterministic.  Therefore, we want to drop the expectation that
-// `a.serialize() = b.serialize() iff a = b` (although we'll maintain
-// `deserialize(a.serialize()) = a`).
-//
-// We have three cases to consider (for some equality function, `eq`):
-// ```
-// eq(a.serialize(), b.serialize()) --> eq(a,b)
-// eq(a, b.serialize())             --> eq(deserialize(a), b)
-// eq(a.serialize(), b)             --> eq(a, deserialize(b))
-// ```
-//
-// `applyFirst` allows us to specify each independently:
-// ```
-// auto eq_fun = functionDecl(...);
-// auto method_call = cxxMemberCallExpr(...);
-//
-// auto two_calls = callExpr(callee(eq_fun), hasArgument(0, method_call),
-//                           hasArgument(1, method_call));
-// auto left_call =
-//     callExpr(callee(eq_fun), callExpr(hasArgument(0, method_call)));
-// auto right_call =
-//     callExpr(callee(eq_fun), callExpr(hasArgument(1, method_call)));
-//
-// RewriteRule R = applyFirst({makeRule(two_calls, two_calls_action),
-//                             makeRule(left_call, left_call_action),
-//                             makeRule(right_call, right_call_action)});
-// ```
-RewriteRule applyFirst(ArrayRef<RewriteRule> Rules);
-
-/// Replaces a portion of the source text with \p Replacement.
-ASTEdit change(RangeSelector Target, TextGenerator Replacement);
-
-/// Replaces the entirety of a RewriteRule's match with \p Replacement.  For
-/// example, to replace a function call, one could write:
-/// \code
-///   makeRule(callExpr(callee(functionDecl(hasName("foo")))),
-///            change(text("bar()")))
-/// \endcode
-inline ASTEdit change(TextGenerator Replacement) {
-  return change(node(RewriteRule::RootID), std::move(Replacement));
-}
-
-/// Inserts \p Replacement before \p S, leaving the source selected by \S
-/// unchanged.
-inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) {
-  return change(before(std::move(S)), std::move(Replacement));
-}
-
-/// Inserts \p Replacement after \p S, leaving the source selected by \S
-/// unchanged.
-inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
-  return change(after(std::move(S)), std::move(Replacement));
-}
-
-/// Removes the source selected by \p S.
-inline ASTEdit remove(RangeSelector S) {
-  return change(std::move(S), text(""));
-}
-
-/// The following three functions are a low-level part of the RewriteRule
-/// API. We expose them for use in implementing the fixtures that interpret
-/// RewriteRule, like Transformer and TransfomerTidy, or for more advanced
-/// users.
-//
-// FIXME: These functions are really public, if advanced, elements of the
-// RewriteRule API.  Recast them as such.  Or, just declare these functions
-// public and well-supported and move them out of `detail`.
-namespace detail {
-/// Builds a single matcher for the rule, covering all of the rule's cases.
-/// Only supports Rules whose cases' matchers share the same base "kind"
-/// (`Stmt`, `Decl`, etc.)  Deprecated: use `buildMatchers` instead, which
-/// supports mixing matchers of different kinds.
-ast_matchers::internal::DynTypedMatcher buildMatcher(const RewriteRule &Rule);
-
-/// Builds a set of matchers that cover the rule (one for each distinct node
-/// matcher base kind: Stmt, Decl, etc.). Node-matchers for `QualType` and
-/// `Type` are not permitted, since such nodes carry no source location
-/// information and are therefore not relevant for rewriting. If any such
-/// matchers are included, will return an empty vector.
-std::vector<ast_matchers::internal::DynTypedMatcher>
-buildMatchers(const RewriteRule &Rule);
-
-/// Gets the beginning location of the source matched by a rewrite rule. If the
-/// match occurs within a macro expansion, returns the beginning of the
-/// expansion point. `Result` must come from the matching of a rewrite rule.
-SourceLocation
-getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result);
-
-/// Returns the \c Case of \c Rule that was selected in the match result.
-/// Assumes a matcher built with \c buildMatcher.
-const RewriteRule::Case &
-findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result,
-                 const RewriteRule &Rule);
-
-/// A source "transformation," represented by a character range in the source to
-/// be replaced and a corresponding replacement string.
-struct Transformation {
-  CharSourceRange Range;
-  std::string Replacement;
-};
-
-/// Attempts to translate `Edits`, which are in terms of AST nodes bound in the
-/// match `Result`, into Transformations, which are in terms of the source code
-/// text.
-///
-/// Returns an empty vector if any of the edits apply to portions of the source
-/// that are ineligible for rewriting (certain interactions with macros, for
-/// example).  Fails if any invariants are violated relating to bound nodes in
-/// the match.  However, it does not fail in the case of conflicting edits --
-/// conflict handling is left to clients.  We recommend use of the \c
-/// AtomicChange or \c Replacements classes for assistance in detecting such
-/// conflicts.
-Expected<SmallVector<Transformation, 1>>
-translateEdits(const ast_matchers::MatchFinder::MatchResult &Result,
-               llvm::ArrayRef<ASTEdit> Edits);
-} // namespace detail
-
-/// Handles the matcher and callback registration for a single rewrite rule, as
-/// defined by the arguments of the constructor.
-class Transformer : public ast_matchers::MatchFinder::MatchCallback {
-public:
-  using ChangeConsumer =
-      std::function<void(Expected<clang::tooling::AtomicChange> Change)>;
-
-  /// \param Consumer Receives each rewrite or error.  Will not necessarily be
-  /// called for each match; for example, if the rewrite is not applicable
-  /// because of macros, but doesn't fail.  Note that clients are responsible
-  /// for handling the case that independent \c AtomicChanges conflict with each
-  /// other.
-  Transformer(RewriteRule Rule, ChangeConsumer Consumer)
-      : Rule(std::move(Rule)), Consumer(std::move(Consumer)) {}
-
-  /// N.B. Passes `this` pointer to `MatchFinder`.  So, this object should not
-  /// be moved after this call.
-  void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
-
-  /// Not called directly by users -- called by the framework, via base class
-  /// pointer.
-  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
-
-private:
-  RewriteRule Rule;
-  /// Receives each successful rewrites as an \c AtomicChange.
-  ChangeConsumer Consumer;
-};
-} // namespace tooling
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLING_REFACTOR_TRANSFORMER_H_

Added: cfe/trunk/include/clang/Tooling/Transformer/MatchConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/MatchConsumer.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/MatchConsumer.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/MatchConsumer.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,58 @@
+//===--- MatchConsumer.h - MatchConsumer abstraction ------------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file defines the *MatchConsumer* abstraction: a computation over
+/// match results, specifically the `ast_matchers::MatchFinder::MatchResult`
+/// class.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_
+
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace tooling {
+
+/// A failable computation over nodes bound by AST matchers.
+///
+/// The computation should report any errors though its return value (rather
+/// than terminating the program) to enable usage in interactive scenarios like
+/// clang-query.
+///
+/// This is a central abstraction of the Transformer framework.
+template <typename T>
+using MatchConsumer =
+    std::function<Expected<T>(const ast_matchers::MatchFinder::MatchResult &)>;
+
+/// Creates an error that signals that a `MatchConsumer` expected a certain node
+/// to be bound by AST matchers, but it was not actually bound.
+inline llvm::Error notBoundError(llvm::StringRef Id) {
+  return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+                                             "Id not bound: " + Id);
+}
+
+/// Chooses between the two consumers, based on whether \p ID is bound in the
+/// match.
+template <typename T>
+MatchConsumer<T> ifBound(std::string ID, MatchConsumer<T> TrueC,
+                         MatchConsumer<T> FalseC) {
+  return [=](const ast_matchers::MatchFinder::MatchResult &Result) {
+    auto &Map = Result.Nodes.getMap();
+    return (Map.find(ID) != Map.end() ? TrueC : FalseC)(Result);
+  };
+}
+
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_MATCH_CONSUMER_H_

Added: cfe/trunk/include/clang/Tooling/Transformer/RangeSelector.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/RangeSelector.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/RangeSelector.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/RangeSelector.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,93 @@
+//===--- RangeSelector.h - Source-selection library ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  Defines a combinator library supporting the definition of _selectors_,
+///  which select source ranges based on (bound) AST nodes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_
+#define LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
+#include "llvm/Support/Error.h"
+#include <functional>
+#include <string>
+
+namespace clang {
+namespace tooling {
+using RangeSelector = MatchConsumer<CharSourceRange>;
+
+inline RangeSelector charRange(CharSourceRange R) {
+  return [R](const ast_matchers::MatchFinder::MatchResult &)
+             -> Expected<CharSourceRange> { return R; };
+}
+
+/// Selects from the start of \p Begin and to the end of \p End.
+RangeSelector range(RangeSelector Begin, RangeSelector End);
+
+/// Convenience version of \c range where end-points are bound nodes.
+RangeSelector range(std::string BeginID, std::string EndID);
+
+/// Selects the (empty) range [B,B) when \p Selector selects the range [B,E).
+RangeSelector before(RangeSelector Selector);
+
+/// Selects the the point immediately following \p Selector. That is, the
+/// (empty) range [E,E), when \p Selector selects either
+/// * the CharRange [B,E) or
+/// * the TokenRange [B,E'] where the token at E' spans the range [E,E').
+RangeSelector after(RangeSelector Selector);
+
+/// Selects a node, including trailing semicolon (for non-expression
+/// statements). \p ID is the node's binding in the match result.
+RangeSelector node(std::string ID);
+
+/// Selects a node, including trailing semicolon (always). Useful for selecting
+/// expression statements. \p ID is the node's binding in the match result.
+RangeSelector statement(std::string ID);
+
+/// Given a \c MemberExpr, selects the member token. \p ID is the node's
+/// binding in the match result.
+RangeSelector member(std::string ID);
+
+/// Given a node with a "name", (like \c NamedDecl, \c DeclRefExpr or \c
+/// CxxCtorInitializer) selects the name's token.  Only selects the final
+/// identifier of a qualified name, but not any qualifiers or template
+/// arguments.  For example, for `::foo::bar::baz` and `::foo::bar::baz<int>`,
+/// it selects only `baz`.
+///
+/// \param ID is the node's binding in the match result.
+RangeSelector name(std::string ID);
+
+// Given a \c CallExpr (bound to \p ID), selects the arguments' source text (all
+// source between the call's parentheses).
+RangeSelector callArgs(std::string ID);
+
+// Given a \c CompoundStmt (bound to \p ID), selects the source of the
+// statements (all source between the braces).
+RangeSelector statements(std::string ID);
+
+// Given a \c InitListExpr (bound to \p ID), selects the range of the elements
+// (all source between the braces).
+RangeSelector initListElements(std::string ID);
+
+/// Given an \IfStmt (bound to \p ID), selects the range of the else branch,
+/// starting from the \c else keyword.
+RangeSelector elseBranch(std::string ID);
+
+/// Selects the range from which `S` was expanded (possibly along with other
+/// source), if `S` is an expansion, and `S` itself, otherwise.  Corresponds to
+/// `SourceManager::getExpansionRange`.
+RangeSelector expansion(RangeSelector S);
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_RANGE_SELECTOR_H_

Added: cfe/trunk/include/clang/Tooling/Transformer/SourceCode.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/SourceCode.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/SourceCode.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/SourceCode.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,90 @@
+//===--- SourceCode.h - Source code manipulation routines -------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides functions that simplify extraction of source code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
+#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
+
+namespace clang {
+namespace tooling {
+
+/// Extends \p Range to include the token \p Next, if it immediately follows the
+/// end of the range. Otherwise, returns \p Range unchanged.
+CharSourceRange maybeExtendRange(CharSourceRange Range, tok::TokenKind Next,
+                                 ASTContext &Context);
+
+/// Returns the source range spanning the node, extended to include \p Next, if
+/// it immediately follows \p Node. Otherwise, returns the normal range of \p
+/// Node.  See comments on `getExtendedText()` for examples.
+template <typename T>
+CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next,
+                                 ASTContext &Context) {
+  return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()),
+                          Next, Context);
+}
+
+/// Returns the source-code text in the specified range.
+StringRef getText(CharSourceRange Range, const ASTContext &Context);
+
+/// Returns the source-code text corresponding to \p Node.
+template <typename T>
+StringRef getText(const T &Node, const ASTContext &Context) {
+  return getText(CharSourceRange::getTokenRange(Node.getSourceRange()),
+                 Context);
+}
+
+/// Returns the source text of the node, extended to include \p Next, if it
+/// immediately follows the node. Otherwise, returns the text of just \p Node.
+///
+/// For example, given statements S1 and S2 below:
+/// \code
+///   {
+///     // S1:
+///     if (!x) return foo();
+///     // S2:
+///     if (!x) { return 3; }
+///   }
+/// \endcode
+/// then
+/// \code
+///   getText(S1, Context) = "if (!x) return foo()"
+///   getExtendedText(S1, tok::TokenKind::semi, Context)
+///     = "if (!x) return foo();"
+///   getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context)
+///     = "return foo();"
+///   getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context)
+///     = getText(S2, Context) = "{ return 3; }"
+/// \endcode
+template <typename T>
+StringRef getExtendedText(const T &Node, tok::TokenKind Next,
+                          ASTContext &Context) {
+  return getText(getExtendedRange(Node, Next, Context), Context);
+}
+
+// Attempts to resolve the given range to one that can be edited by a rewrite;
+// generally, one that starts and ends within a particular file. It supports
+// a limited set of cases involving source locations in macro expansions.
+llvm::Optional<CharSourceRange>
+getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM,
+                const LangOptions &LangOpts);
+
+inline llvm::Optional<CharSourceRange>
+getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) {
+  return getRangeForEdit(EditRange, Context.getSourceManager(),
+                         Context.getLangOpts());
+}
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H

Added: cfe/trunk/include/clang/Tooling/Transformer/SourceCodeBuilders.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/SourceCodeBuilders.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/SourceCodeBuilders.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/SourceCodeBuilders.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,86 @@
+//===--- SourceCodeBuilders.h - Source-code building facilities -*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file collects facilities for generating source code strings.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include <string>
+
+namespace clang {
+namespace tooling {
+
+/// \name Code analysis utilities.
+/// @{
+/// Ignores implicit object-construction expressions in addition to the normal
+/// implicit expressions that are ignored.
+const Expr *reallyIgnoreImplicit(const Expr &E);
+
+/// Determines whether printing this expression in *any* expression requires
+/// parentheses to preserve its meaning. This analyses is necessarily
+/// conservative because it lacks information about the target context.
+bool mayEverNeedParens(const Expr &E);
+
+/// Determines whether printing this expression to the left of a dot or arrow
+/// operator requires a parentheses to preserve its meaning. Given that
+/// dot/arrow are (effectively) the highest precedence, this is equivalent to
+/// asking whether it ever needs parens.
+inline bool needParensBeforeDotOrArrow(const Expr &E) {
+  return mayEverNeedParens(E);
+}
+
+/// Determines whether printing this expression to the right of a unary operator
+/// requires a parentheses to preserve its meaning.
+bool needParensAfterUnaryOperator(const Expr &E);
+/// @}
+
+/// \name Basic code-string generation utilities.
+/// @{
+
+/// Builds source for an expression, adding parens if needed for unambiguous
+/// parsing.
+llvm::Optional<std::string> buildParens(const Expr &E,
+                                        const ASTContext &Context);
+
+/// Builds idiomatic source for the dereferencing of `E`: prefix with `*` but
+/// simplify when it already begins with `&`.  \returns empty string on failure.
+llvm::Optional<std::string> buildDereference(const Expr &E,
+                                             const ASTContext &Context);
+
+/// Builds idiomatic source for taking the address of `E`: prefix with `&` but
+/// simplify when it already begins with `*`.  \returns empty string on failure.
+llvm::Optional<std::string> buildAddressOf(const Expr &E,
+                                           const ASTContext &Context);
+
+/// Adds a dot to the end of the given expression, but adds parentheses when
+/// needed by the syntax, and simplifies to `->` when possible, e.g.:
+///
+///  `x` becomes `x.`
+///  `*a` becomes `a->`
+///  `a+b` becomes `(a+b).`
+llvm::Optional<std::string> buildDot(const Expr &E, const ASTContext &Context);
+
+/// Adds an arrow to the end of the given expression, but adds parentheses
+/// when needed by the syntax, and simplifies to `.` when possible, e.g.:
+///
+///  `x` becomes `x->`
+///  `&a` becomes `a.`
+///  `a+b` becomes `(a+b)->`
+llvm::Optional<std::string> buildArrow(const Expr &E,
+                                       const ASTContext &Context);
+/// @}
+
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_BUILDERS_H_

Added: cfe/trunk/include/clang/Tooling/Transformer/Stencil.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/Stencil.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/Stencil.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/Stencil.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,226 @@
+//===--- Stencil.h - Stencil class ------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the *Stencil* abstraction: a code-generating object,
+/// parameterized by named references to (bound) AST nodes.  Given a match
+/// result, a stencil can be evaluated to a string of source code.
+///
+/// A stencil is similar in spirit to a format string: it is composed of a
+/// series of raw text strings, references to nodes (the parameters) and helper
+/// code-generation operations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace tooling {
+
+/// A stencil is represented as a sequence of "parts" that can each individually
+/// generate a code string based on a match result.  The different kinds of
+/// parts include (raw) text, references to bound nodes and assorted operations
+/// on bound nodes.
+///
+/// Users can create custom Stencil operations by implementing this interface.
+class StencilPartInterface {
+public:
+  virtual ~StencilPartInterface() = default;
+
+  /// Evaluates this part to a string and appends it to \c Result.  \c Result is
+  /// undefined in the case of an error.
+  virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
+                           std::string *Result) const = 0;
+
+  virtual bool isEqual(const StencilPartInterface &other) const = 0;
+
+  /// Constructs a string representation of the StencilPart. StencilParts
+  /// generated by the `selection` and `run` functions do not have a unique
+  /// string representation.
+  virtual std::string toString() const = 0;
+
+  const void *typeId() const { return TypeId; }
+
+protected:
+  StencilPartInterface(const void *DerivedId) : TypeId(DerivedId) {}
+
+  // Since this is an abstract class, copying/assigning only make sense for
+  // derived classes implementing `clone()`.
+  StencilPartInterface(const StencilPartInterface &) = default;
+  StencilPartInterface &operator=(const StencilPartInterface &) = default;
+
+  /// Unique identifier of the concrete type of this instance.  Supports safe
+  /// downcasting.
+  const void *TypeId;
+};
+
+/// A copyable facade for a std::unique_ptr<StencilPartInterface>. Copies result
+/// in a copy of the underlying pointee object.
+class StencilPart {
+public:
+  explicit StencilPart(std::shared_ptr<StencilPartInterface> Impl)
+      : Impl(std::move(Impl)) {}
+
+  /// See `StencilPartInterface::eval()`.
+  llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
+                   std::string *Result) const {
+    return Impl->eval(Match, Result);
+  }
+
+  bool operator==(const StencilPart &Other) const {
+    if (Impl == Other.Impl)
+      return true;
+    if (Impl == nullptr || Other.Impl == nullptr)
+      return false;
+    return Impl->isEqual(*Other.Impl);
+  }
+
+  std::string toString() const {
+    if (Impl == nullptr)
+      return "";
+    return Impl->toString();
+  }
+
+private:
+  std::shared_ptr<StencilPartInterface> Impl;
+};
+
+/// A sequence of code fragments, references to parameters and code-generation
+/// operations that together can be evaluated to (a fragment of) source code,
+/// given a match result.
+class Stencil {
+public:
+  Stencil() = default;
+
+  /// Composes a stencil from a series of parts.
+  template <typename... Ts> static Stencil cat(Ts &&... Parts) {
+    Stencil S;
+    S.Parts = {wrap(std::forward<Ts>(Parts))...};
+    return S;
+  }
+
+  /// Appends data from a \p OtherStencil to this stencil.
+  void append(Stencil OtherStencil);
+
+  // Evaluates the stencil given a match result. Requires that the nodes in the
+  // result includes any ids referenced in the stencil. References to missing
+  // nodes will result in an invalid_argument error.
+  llvm::Expected<std::string>
+  eval(const ast_matchers::MatchFinder::MatchResult &Match) const;
+
+  // Allow Stencils to operate as std::function, for compatibility with
+  // Transformer's TextGenerator.
+  llvm::Expected<std::string>
+  operator()(const ast_matchers::MatchFinder::MatchResult &Result) const {
+    return eval(Result);
+  }
+
+  /// Constructs a string representation of the Stencil. The string is not
+  /// guaranteed to be unique.
+  std::string toString() const {
+    std::vector<std::string> PartStrings;
+    PartStrings.reserve(Parts.size());
+    for (const auto &Part : Parts)
+      PartStrings.push_back(Part.toString());
+    return llvm::join(PartStrings, ", ");
+  }
+
+private:
+  friend bool operator==(const Stencil &A, const Stencil &B);
+  static StencilPart wrap(llvm::StringRef Text);
+  static StencilPart wrap(RangeSelector Selector);
+  static StencilPart wrap(StencilPart Part) { return Part; }
+
+  std::vector<StencilPart> Parts;
+};
+
+inline bool operator==(const Stencil &A, const Stencil &B) {
+  return A.Parts == B.Parts;
+}
+
+inline bool operator!=(const Stencil &A, const Stencil &B) { return !(A == B); }
+
+// Functions for conveniently building stencils.
+namespace stencil {
+/// Convenience wrapper for Stencil::cat that can be imported with a using decl.
+template <typename... Ts> Stencil cat(Ts &&... Parts) {
+  return Stencil::cat(std::forward<Ts>(Parts)...);
+}
+
+/// \returns exactly the text provided.
+StencilPart text(llvm::StringRef Text);
+
+/// \returns the source corresponding to the selected range.
+StencilPart selection(RangeSelector Selector);
+
+/// \returns the source corresponding to the identified node.
+/// FIXME: Deprecated. Write `selection(node(Id))` instead.
+inline StencilPart node(llvm::StringRef Id) {
+  return selection(tooling::node(Id));
+}
+
+/// Generates the source of the expression bound to \p Id, wrapping it in
+/// parentheses if it may parse differently depending on context. For example, a
+/// binary operation is always wrapped, while a variable reference is never
+/// wrapped.
+StencilPart expression(llvm::StringRef Id);
+
+/// Constructs an idiomatic dereferencing of the expression bound to \p ExprId.
+/// \p ExprId is wrapped in parentheses, if needed.
+StencilPart deref(llvm::StringRef ExprId);
+
+/// Constructs an expression that idiomatically takes the address of the
+/// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if
+/// needed.
+StencilPart addressOf(llvm::StringRef ExprId);
+
+/// Constructs a `MemberExpr` that accesses the named member (\p Member) of the
+/// object bound to \p BaseId. The access is constructed idiomatically: if \p
+/// BaseId is bound to `e` and \p Member identifies member `m`, then returns
+/// `e->m`, when e is a pointer, `e2->m` when e = `*e2` and `e.m` otherwise.
+/// Additionally, `e` is wrapped in parentheses, if needed.
+StencilPart access(llvm::StringRef BaseId, StencilPart Member);
+inline StencilPart access(llvm::StringRef BaseId, llvm::StringRef Member) {
+  return access(BaseId, text(Member));
+}
+
+/// Chooses between the two stencil parts, based on whether \p ID is bound in
+/// the match.
+StencilPart ifBound(llvm::StringRef Id, StencilPart TruePart,
+                    StencilPart FalsePart);
+
+/// Chooses between the two strings, based on whether \p ID is bound in the
+/// match.
+inline StencilPart ifBound(llvm::StringRef Id, llvm::StringRef TrueText,
+                           llvm::StringRef FalseText) {
+  return ifBound(Id, text(TrueText), text(FalseText));
+}
+
+/// Wraps a MatchConsumer in a StencilPart, so that it can be used in a Stencil.
+/// This supports user-defined extensions to the Stencil language.
+StencilPart run(MatchConsumer<std::string> C);
+
+/// For debug use only; semantics are not guaranteed.
+///
+/// \returns the string resulting from calling the node's print() method.
+StencilPart dPrint(llvm::StringRef Id);
+} // namespace stencil
+} // namespace tooling
+} // namespace clang
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_STENCIL_H_

Added: cfe/trunk/include/clang/Tooling/Transformer/Transformer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/Transformer/Transformer.h?rev=374271&view=auto
==============================================================================
--- cfe/trunk/include/clang/Tooling/Transformer/Transformer.h (added)
+++ cfe/trunk/include/clang/Tooling/Transformer/Transformer.h Wed Oct  9 19:34:47 2019
@@ -0,0 +1,320 @@
+//===--- Transformer.h - Clang source-rewriting library ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+///  \file
+///  Defines a library supporting the concise specification of clang-based
+///  source-to-source transformations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_
+#define LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/ASTMatchersInternal.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Transformer/MatchConsumer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Error.h"
+#include <deque>
+#include <functional>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+namespace clang {
+namespace tooling {
+
+using TextGenerator = MatchConsumer<std::string>;
+
+/// Wraps a string as a TextGenerator.
+inline TextGenerator text(std::string M) {
+  return [M](const ast_matchers::MatchFinder::MatchResult &)
+             -> Expected<std::string> { return M; };
+}
+
+// Description of a source-code edit, expressed in terms of an AST node.
+// Includes: an ID for the (bound) node, a selector for source related to the
+// node, a replacement and, optionally, an explanation for the edit.
+//
+// * Target: the source code impacted by the rule. This identifies an AST node,
+//   or part thereof (\c Part), whose source range indicates the extent of the
+//   replacement applied by the replacement term.  By default, the extent is the
+//   node matched by the pattern term (\c NodePart::Node). Target's are typed
+//   (\c Kind), which guides the determination of the node extent.
+//
+// * Replacement: a function that produces a replacement string for the target,
+//   based on the match result.
+//
+// * Note: (optional) a note specifically for this edit, potentially referencing
+//   elements of the match.  This will be displayed to the user, where possible;
+//   for example, in clang-tidy diagnostics.  Use of notes should be rare --
+//   explanations of the entire rewrite should be set in the rule
+//   (`RewriteRule::Explanation`) instead.  Notes serve the rare cases wherein
+//   edit-specific diagnostics are required.
+//
+// `ASTEdit` should be built using the `change` convenience functions. For
+// example,
+// \code
+//   change(name(fun), text("Frodo"))
+// \endcode
+// Or, if we use Stencil for the TextGenerator:
+// \code
+//   using stencil::cat;
+//   change(statement(thenNode), cat("{", thenNode, "}"))
+//   change(callArgs(call), cat(x, ",", y))
+// \endcode
+// Or, if you are changing the node corresponding to the rule's matcher, you can
+// use the single-argument override of \c change:
+// \code
+//   change(cat("different_expr"))
+// \endcode
+struct ASTEdit {
+  RangeSelector TargetRange;
+  TextGenerator Replacement;
+  TextGenerator Note;
+};
+
+/// Format of the path in an include directive -- angle brackets or quotes.
+enum class IncludeFormat {
+  Quoted,
+  Angled,
+};
+
+/// Description of a source-code transformation.
+//
+// A *rewrite rule* describes a transformation of source code. A simple rule
+// contains each of the following components:
+//
+// * Matcher: the pattern term, expressed as clang matchers (with Transformer
+//   extensions).
+//
+// * Edits: a set of Edits to the source code, described with ASTEdits.
+//
+// * Explanation: explanation of the rewrite.  This will be displayed to the
+//   user, where possible; for example, in clang-tidy diagnostics.
+//
+// However, rules can also consist of (sub)rules, where the first that matches
+// is applied and the rest are ignored.  So, the above components are gathered
+// as a `Case` and a rule is a list of cases.
+//
+// Rule cases have an additional, implicit, component: the parameters. These are
+// portions of the pattern which are left unspecified, yet bound in the pattern
+// so that we can reference them in the edits.
+//
+// The \c Transformer class can be used to apply the rewrite rule and obtain the
+// corresponding replacements.
+struct RewriteRule {
+  struct Case {
+    ast_matchers::internal::DynTypedMatcher Matcher;
+    SmallVector<ASTEdit, 1> Edits;
+    TextGenerator Explanation;
+    // Include paths to add to the file affected by this case.  These are
+    // bundled with the `Case`, rather than the `RewriteRule`, because each case
+    // might have different associated changes to the includes.
+    std::vector<std::pair<std::string, IncludeFormat>> AddedIncludes;
+  };
+  // We expect RewriteRules will most commonly include only one case.
+  SmallVector<Case, 1> Cases;
+
+  // ID used as the default target of each match. The node described by the
+  // matcher is should always be bound to this id.
+  static constexpr llvm::StringLiteral RootID = "___root___";
+};
+
+/// Convenience function for constructing a simple \c RewriteRule.
+RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
+                     SmallVector<ASTEdit, 1> Edits,
+                     TextGenerator Explanation = nullptr);
+
+/// Convenience overload of \c makeRule for common case of only one edit.
+inline RewriteRule makeRule(ast_matchers::internal::DynTypedMatcher M,
+                            ASTEdit Edit,
+                            TextGenerator Explanation = nullptr) {
+  SmallVector<ASTEdit, 1> Edits;
+  Edits.emplace_back(std::move(Edit));
+  return makeRule(std::move(M), std::move(Edits), std::move(Explanation));
+}
+
+/// For every case in Rule, adds an include directive for the given header. The
+/// common use is assumed to be a rule with only one case. For example, to
+/// replace a function call and add headers corresponding to the new code, one
+/// could write:
+/// \code
+///   auto R = makeRule(callExpr(callee(functionDecl(hasName("foo")))),
+///            change(text("bar()")));
+///   AddInclude(R, "path/to/bar_header.h");
+///   AddInclude(R, "vector", IncludeFormat::Angled);
+/// \endcode
+void addInclude(RewriteRule &Rule, llvm::StringRef Header,
+                IncludeFormat Format = IncludeFormat::Quoted);
+
+/// Applies the first rule whose pattern matches; other rules are ignored.  If
+/// the matchers are independent then order doesn't matter. In that case,
+/// `applyFirst` is simply joining the set of rules into one.
+//
+// `applyFirst` is like an `anyOf` matcher with an edit action attached to each
+// of its cases. Anywhere you'd use `anyOf(m1.bind("id1"), m2.bind("id2"))` and
+// then dispatch on those ids in your code for control flow, `applyFirst` lifts
+// that behavior to the rule level.  So, you can write `applyFirst({makeRule(m1,
+// action1), makeRule(m2, action2), ...});`
+//
+// For example, consider a type `T` with a deterministic serialization function,
+// `serialize()`.  For performance reasons, we would like to make it
+// non-deterministic.  Therefore, we want to drop the expectation that
+// `a.serialize() = b.serialize() iff a = b` (although we'll maintain
+// `deserialize(a.serialize()) = a`).
+//
+// We have three cases to consider (for some equality function, `eq`):
+// ```
+// eq(a.serialize(), b.serialize()) --> eq(a,b)
+// eq(a, b.serialize())             --> eq(deserialize(a), b)
+// eq(a.serialize(), b)             --> eq(a, deserialize(b))
+// ```
+//
+// `applyFirst` allows us to specify each independently:
+// ```
+// auto eq_fun = functionDecl(...);
+// auto method_call = cxxMemberCallExpr(...);
+//
+// auto two_calls = callExpr(callee(eq_fun), hasArgument(0, method_call),
+//                           hasArgument(1, method_call));
+// auto left_call =
+//     callExpr(callee(eq_fun), callExpr(hasArgument(0, method_call)));
+// auto right_call =
+//     callExpr(callee(eq_fun), callExpr(hasArgument(1, method_call)));
+//
+// RewriteRule R = applyFirst({makeRule(two_calls, two_calls_action),
+//                             makeRule(left_call, left_call_action),
+//                             makeRule(right_call, right_call_action)});
+// ```
+RewriteRule applyFirst(ArrayRef<RewriteRule> Rules);
+
+/// Replaces a portion of the source text with \p Replacement.
+ASTEdit change(RangeSelector Target, TextGenerator Replacement);
+
+/// Replaces the entirety of a RewriteRule's match with \p Replacement.  For
+/// example, to replace a function call, one could write:
+/// \code
+///   makeRule(callExpr(callee(functionDecl(hasName("foo")))),
+///            change(text("bar()")))
+/// \endcode
+inline ASTEdit change(TextGenerator Replacement) {
+  return change(node(RewriteRule::RootID), std::move(Replacement));
+}
+
+/// Inserts \p Replacement before \p S, leaving the source selected by \S
+/// unchanged.
+inline ASTEdit insertBefore(RangeSelector S, TextGenerator Replacement) {
+  return change(before(std::move(S)), std::move(Replacement));
+}
+
+/// Inserts \p Replacement after \p S, leaving the source selected by \S
+/// unchanged.
+inline ASTEdit insertAfter(RangeSelector S, TextGenerator Replacement) {
+  return change(after(std::move(S)), std::move(Replacement));
+}
+
+/// Removes the source selected by \p S.
+inline ASTEdit remove(RangeSelector S) {
+  return change(std::move(S), text(""));
+}
+
+/// The following three functions are a low-level part of the RewriteRule
+/// API. We expose them for use in implementing the fixtures that interpret
+/// RewriteRule, like Transformer and TransfomerTidy, or for more advanced
+/// users.
+//
+// FIXME: These functions are really public, if advanced, elements of the
+// RewriteRule API.  Recast them as such.  Or, just declare these functions
+// public and well-supported and move them out of `detail`.
+namespace detail {
+/// Builds a single matcher for the rule, covering all of the rule's cases.
+/// Only supports Rules whose cases' matchers share the same base "kind"
+/// (`Stmt`, `Decl`, etc.)  Deprecated: use `buildMatchers` instead, which
+/// supports mixing matchers of different kinds.
+ast_matchers::internal::DynTypedMatcher buildMatcher(const RewriteRule &Rule);
+
+/// Builds a set of matchers that cover the rule (one for each distinct node
+/// matcher base kind: Stmt, Decl, etc.). Node-matchers for `QualType` and
+/// `Type` are not permitted, since such nodes carry no source location
+/// information and are therefore not relevant for rewriting. If any such
+/// matchers are included, will return an empty vector.
+std::vector<ast_matchers::internal::DynTypedMatcher>
+buildMatchers(const RewriteRule &Rule);
+
+/// Gets the beginning location of the source matched by a rewrite rule. If the
+/// match occurs within a macro expansion, returns the beginning of the
+/// expansion point. `Result` must come from the matching of a rewrite rule.
+SourceLocation
+getRuleMatchLoc(const ast_matchers::MatchFinder::MatchResult &Result);
+
+/// Returns the \c Case of \c Rule that was selected in the match result.
+/// Assumes a matcher built with \c buildMatcher.
+const RewriteRule::Case &
+findSelectedCase(const ast_matchers::MatchFinder::MatchResult &Result,
+                 const RewriteRule &Rule);
+
+/// A source "transformation," represented by a character range in the source to
+/// be replaced and a corresponding replacement string.
+struct Transformation {
+  CharSourceRange Range;
+  std::string Replacement;
+};
+
+/// Attempts to translate `Edits`, which are in terms of AST nodes bound in the
+/// match `Result`, into Transformations, which are in terms of the source code
+/// text.
+///
+/// Returns an empty vector if any of the edits apply to portions of the source
+/// that are ineligible for rewriting (certain interactions with macros, for
+/// example).  Fails if any invariants are violated relating to bound nodes in
+/// the match.  However, it does not fail in the case of conflicting edits --
+/// conflict handling is left to clients.  We recommend use of the \c
+/// AtomicChange or \c Replacements classes for assistance in detecting such
+/// conflicts.
+Expected<SmallVector<Transformation, 1>>
+translateEdits(const ast_matchers::MatchFinder::MatchResult &Result,
+               llvm::ArrayRef<ASTEdit> Edits);
+} // namespace detail
+
+/// Handles the matcher and callback registration for a single rewrite rule, as
+/// defined by the arguments of the constructor.
+class Transformer : public ast_matchers::MatchFinder::MatchCallback {
+public:
+  using ChangeConsumer =
+      std::function<void(Expected<clang::tooling::AtomicChange> Change)>;
+
+  /// \param Consumer Receives each rewrite or error.  Will not necessarily be
+  /// called for each match; for example, if the rewrite is not applicable
+  /// because of macros, but doesn't fail.  Note that clients are responsible
+  /// for handling the case that independent \c AtomicChanges conflict with each
+  /// other.
+  Transformer(RewriteRule Rule, ChangeConsumer Consumer)
+      : Rule(std::move(Rule)), Consumer(std::move(Consumer)) {}
+
+  /// N.B. Passes `this` pointer to `MatchFinder`.  So, this object should not
+  /// be moved after this call.
+  void registerMatchers(ast_matchers::MatchFinder *MatchFinder);
+
+  /// Not called directly by users -- called by the framework, via base class
+  /// pointer.
+  void run(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  RewriteRule Rule;
+  /// Receives each successful rewrites as an \c AtomicChange.
+  ChangeConsumer Consumer;
+};
+} // namespace tooling
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLING_TRANSFORMER_TRANSFORMER_H_

Modified: cfe/trunk/lib/Tooling/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/CMakeLists.txt?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/CMakeLists.txt (original)
+++ cfe/trunk/lib/Tooling/CMakeLists.txt Wed Oct  9 19:34:47 2019
@@ -9,6 +9,7 @@ add_subdirectory(Refactoring)
 add_subdirectory(ASTDiff)
 add_subdirectory(Syntax)
 add_subdirectory(DependencyScanning)
+add_subdirectory(Transformer)
 
 add_clang_library(clangTooling
   AllTUsExecution.cpp

Modified: cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt (original)
+++ cfe/trunk/lib/Tooling/Refactoring/CMakeLists.txt Wed Oct  9 19:34:47 2019
@@ -6,17 +6,12 @@ add_clang_library(clangToolingRefactorin
   AtomicChange.cpp
   Extract/Extract.cpp
   Extract/SourceExtraction.cpp
-  RangeSelector.cpp
   RefactoringActions.cpp
   Rename/RenamingAction.cpp
   Rename/SymbolOccurrences.cpp
   Rename/USRFinder.cpp
   Rename/USRFindingAction.cpp
   Rename/USRLocFinder.cpp
-  SourceCode.cpp
-  SourceCodeBuilders.cpp
-  Stencil.cpp
-  Transformer.cpp
 
   LINK_LIBS
   clangAST

Removed: cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp?rev=374270&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/RangeSelector.cpp (removed)
@@ -1,312 +0,0 @@
-//===--- RangeSelector.cpp - RangeSelector implementations ------*- 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 "clang/Tooling/Refactoring/RangeSelector.h"
-#include "clang/AST/Expr.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/Refactoring/SourceCode.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-using namespace tooling;
-
-using ast_matchers::MatchFinder;
-using ast_type_traits::ASTNodeKind;
-using ast_type_traits::DynTypedNode;
-using llvm::Error;
-using llvm::StringError;
-
-using MatchResult = MatchFinder::MatchResult;
-
-static Error invalidArgumentError(Twine Message) {
-  return llvm::make_error<StringError>(llvm::errc::invalid_argument, Message);
-}
-
-static Error typeError(StringRef ID, const ASTNodeKind &Kind) {
-  return invalidArgumentError("mismatched type (node id=" + ID +
-                              " kind=" + Kind.asStringRef() + ")");
-}
-
-static Error typeError(StringRef ID, const ASTNodeKind &Kind,
-                       Twine ExpectedType) {
-  return invalidArgumentError("mismatched type: expected one of " +
-                              ExpectedType + " (node id=" + ID +
-                              " kind=" + Kind.asStringRef() + ")");
-}
-
-static Error missingPropertyError(StringRef ID, Twine Description,
-                                  StringRef Property) {
-  return invalidArgumentError(Description + " requires property '" + Property +
-                              "' (node id=" + ID + ")");
-}
-
-static Expected<DynTypedNode> getNode(const ast_matchers::BoundNodes &Nodes,
-                                      StringRef ID) {
-  auto &NodesMap = Nodes.getMap();
-  auto It = NodesMap.find(ID);
-  if (It == NodesMap.end())
-    return invalidArgumentError("ID not bound: " + ID);
-  return It->second;
-}
-
-// FIXME: handling of macros should be configurable.
-static SourceLocation findPreviousTokenStart(SourceLocation Start,
-                                             const SourceManager &SM,
-                                             const LangOptions &LangOpts) {
-  if (Start.isInvalid() || Start.isMacroID())
-    return SourceLocation();
-
-  SourceLocation BeforeStart = Start.getLocWithOffset(-1);
-  if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
-    return SourceLocation();
-
-  return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
-}
-
-// Finds the start location of the previous token of kind \p TK.
-// FIXME: handling of macros should be configurable.
-static SourceLocation findPreviousTokenKind(SourceLocation Start,
-                                            const SourceManager &SM,
-                                            const LangOptions &LangOpts,
-                                            tok::TokenKind TK) {
-  while (true) {
-    SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
-    if (L.isInvalid() || L.isMacroID())
-      return SourceLocation();
-
-    Token T;
-    if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
-      return SourceLocation();
-
-    if (T.is(TK))
-      return T.getLocation();
-
-    Start = L;
-  }
-}
-
-static SourceLocation findOpenParen(const CallExpr &E, const SourceManager &SM,
-                                    const LangOptions &LangOpts) {
-  SourceLocation EndLoc =
-      E.getNumArgs() == 0 ? E.getRParenLoc() : E.getArg(0)->getBeginLoc();
-  return findPreviousTokenKind(EndLoc, SM, LangOpts, tok::TokenKind::l_paren);
-}
-
-RangeSelector tooling::before(RangeSelector Selector) {
-  return [Selector](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<CharSourceRange> SelectedRange = Selector(Result);
-    if (!SelectedRange)
-      return SelectedRange.takeError();
-    return CharSourceRange::getCharRange(SelectedRange->getBegin());
-  };
-}
-
-RangeSelector tooling::after(RangeSelector Selector) {
-  return [Selector](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<CharSourceRange> SelectedRange = Selector(Result);
-    if (!SelectedRange)
-      return SelectedRange.takeError();
-    if (SelectedRange->isCharRange())
-      return CharSourceRange::getCharRange(SelectedRange->getEnd());
-    return CharSourceRange::getCharRange(Lexer::getLocForEndOfToken(
-        SelectedRange->getEnd(), 0, Result.Context->getSourceManager(),
-        Result.Context->getLangOpts()));
-  };
-}
-
-RangeSelector tooling::node(std::string ID) {
-  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
-    if (!Node)
-      return Node.takeError();
-    return Node->get<Stmt>() != nullptr && Node->get<Expr>() == nullptr
-               ? getExtendedRange(*Node, tok::TokenKind::semi, *Result.Context)
-               : CharSourceRange::getTokenRange(Node->getSourceRange());
-  };
-}
-
-RangeSelector tooling::statement(std::string ID) {
-  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
-    if (!Node)
-      return Node.takeError();
-    return getExtendedRange(*Node, tok::TokenKind::semi, *Result.Context);
-  };
-}
-
-RangeSelector tooling::range(RangeSelector Begin, RangeSelector End) {
-  return [Begin, End](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<CharSourceRange> BeginRange = Begin(Result);
-    if (!BeginRange)
-      return BeginRange.takeError();
-    Expected<CharSourceRange> EndRange = End(Result);
-    if (!EndRange)
-      return EndRange.takeError();
-    SourceLocation B = BeginRange->getBegin();
-    SourceLocation E = EndRange->getEnd();
-    // Note: we are precluding the possibility of sub-token ranges in the case
-    // that EndRange is a token range.
-    if (Result.SourceManager->isBeforeInTranslationUnit(E, B)) {
-      return invalidArgumentError("Bad range: out of order");
-    }
-    return CharSourceRange(SourceRange(B, E), EndRange->isTokenRange());
-  };
-}
-
-RangeSelector tooling::range(std::string BeginID, std::string EndID) {
-  return tooling::range(node(std::move(BeginID)), node(std::move(EndID)));
-}
-
-RangeSelector tooling::member(std::string ID) {
-  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
-    if (!Node)
-      return Node.takeError();
-    if (auto *M = Node->get<clang::MemberExpr>())
-      return CharSourceRange::getTokenRange(
-          M->getMemberNameInfo().getSourceRange());
-    return typeError(ID, Node->getNodeKind(), "MemberExpr");
-  };
-}
-
-RangeSelector tooling::name(std::string ID) {
-  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<DynTypedNode> N = getNode(Result.Nodes, ID);
-    if (!N)
-      return N.takeError();
-    auto &Node = *N;
-    if (const auto *D = Node.get<NamedDecl>()) {
-      if (!D->getDeclName().isIdentifier())
-        return missingPropertyError(ID, "name", "identifier");
-      SourceLocation L = D->getLocation();
-      auto R = CharSourceRange::getTokenRange(L, L);
-      // Verify that the range covers exactly the name.
-      // FIXME: extend this code to support cases like `operator +` or
-      // `foo<int>` for which this range will be too short.  Doing so will
-      // require subcasing `NamedDecl`, because it doesn't provide virtual
-      // access to the \c DeclarationNameInfo.
-      if (getText(R, *Result.Context) != D->getName())
-        return CharSourceRange();
-      return R;
-    }
-    if (const auto *E = Node.get<DeclRefExpr>()) {
-      if (!E->getNameInfo().getName().isIdentifier())
-        return missingPropertyError(ID, "name", "identifier");
-      SourceLocation L = E->getLocation();
-      return CharSourceRange::getTokenRange(L, L);
-    }
-    if (const auto *I = Node.get<CXXCtorInitializer>()) {
-      if (!I->isMemberInitializer() && I->isWritten())
-        return missingPropertyError(ID, "name", "explicit member initializer");
-      SourceLocation L = I->getMemberLocation();
-      return CharSourceRange::getTokenRange(L, L);
-    }
-    return typeError(ID, Node.getNodeKind(),
-                     "DeclRefExpr, NamedDecl, CXXCtorInitializer");
-  };
-}
-
-namespace {
-// FIXME: make this available in the public API for users to easily create their
-// own selectors.
-
-// Creates a selector from a range-selection function \p Func, which selects a
-// range that is relative to a bound node id.  \c T is the node type expected by
-// \p Func.
-template <typename T, CharSourceRange (*Func)(const MatchResult &, const T &)>
-class RelativeSelector {
-  std::string ID;
-
-public:
-  RelativeSelector(std::string ID) : ID(std::move(ID)) {}
-
-  Expected<CharSourceRange> operator()(const MatchResult &Result) {
-    Expected<DynTypedNode> N = getNode(Result.Nodes, ID);
-    if (!N)
-      return N.takeError();
-    if (const auto *Arg = N->get<T>())
-      return Func(Result, *Arg);
-    return typeError(ID, N->getNodeKind());
-  }
-};
-} // namespace
-
-// FIXME: Change the following functions from being in an anonymous namespace
-// to static functions, after the minimum Visual C++ has _MSC_VER >= 1915
-// (equivalent to Visual Studio 2017 v15.8 or higher). Using the anonymous
-// namespace works around a bug in earlier versions.
-namespace {
-// Returns the range of the statements (all source between the braces).
-CharSourceRange getStatementsRange(const MatchResult &,
-                                   const CompoundStmt &CS) {
-  return CharSourceRange::getCharRange(CS.getLBracLoc().getLocWithOffset(1),
-                                       CS.getRBracLoc());
-}
-} // namespace
-
-RangeSelector tooling::statements(std::string ID) {
-  return RelativeSelector<CompoundStmt, getStatementsRange>(std::move(ID));
-}
-
-namespace {
-// Returns the range of the source between the call's parentheses.
-CharSourceRange getCallArgumentsRange(const MatchResult &Result,
-                                      const CallExpr &CE) {
-  return CharSourceRange::getCharRange(
-      findOpenParen(CE, *Result.SourceManager, Result.Context->getLangOpts())
-          .getLocWithOffset(1),
-      CE.getRParenLoc());
-}
-} // namespace
-
-RangeSelector tooling::callArgs(std::string ID) {
-  return RelativeSelector<CallExpr, getCallArgumentsRange>(std::move(ID));
-}
-
-namespace {
-// Returns the range of the elements of the initializer list. Includes all
-// source between the braces.
-CharSourceRange getElementsRange(const MatchResult &,
-                                 const InitListExpr &E) {
-  return CharSourceRange::getCharRange(E.getLBraceLoc().getLocWithOffset(1),
-                                       E.getRBraceLoc());
-}
-} // namespace
-
-RangeSelector tooling::initListElements(std::string ID) {
-  return RelativeSelector<InitListExpr, getElementsRange>(std::move(ID));
-}
-
-namespace {
-// Returns the range of the else branch, including the `else` keyword.
-CharSourceRange getElseRange(const MatchResult &Result, const IfStmt &S) {
-  return maybeExtendRange(
-      CharSourceRange::getTokenRange(S.getElseLoc(), S.getEndLoc()),
-      tok::TokenKind::semi, *Result.Context);
-}
-} // namespace
-
-RangeSelector tooling::elseBranch(std::string ID) {
-  return RelativeSelector<IfStmt, getElseRange>(std::move(ID));
-}
-
-RangeSelector tooling::expansion(RangeSelector S) {
-  return [S](const MatchResult &Result) -> Expected<CharSourceRange> {
-    Expected<CharSourceRange> SRange = S(Result);
-    if (!SRange)
-      return SRange.takeError();
-    return Result.SourceManager->getExpansionRange(*SRange);
-  };
-}

Removed: cfe/trunk/lib/Tooling/Refactoring/SourceCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/SourceCode.cpp?rev=374270&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/SourceCode.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/SourceCode.cpp (removed)
@@ -1,65 +0,0 @@
-//===--- SourceCode.cpp - Source code manipulation routines -----*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file provides functions that simplify extraction of source code.
-//
-//===----------------------------------------------------------------------===//
-#include "clang/Tooling/Refactoring/SourceCode.h"
-#include "clang/Lex/Lexer.h"
-
-using namespace clang;
-
-StringRef clang::tooling::getText(CharSourceRange Range,
-                                  const ASTContext &Context) {
-  return Lexer::getSourceText(Range, Context.getSourceManager(),
-                              Context.getLangOpts());
-}
-
-CharSourceRange clang::tooling::maybeExtendRange(CharSourceRange Range,
-                                                 tok::TokenKind Next,
-                                                 ASTContext &Context) {
-  Optional<Token> Tok = Lexer::findNextToken(
-      Range.getEnd(), Context.getSourceManager(), Context.getLangOpts());
-  if (!Tok || !Tok->is(Next))
-    return Range;
-  return CharSourceRange::getTokenRange(Range.getBegin(), Tok->getLocation());
-}
-
-llvm::Optional<CharSourceRange>
-clang::tooling::getRangeForEdit(const CharSourceRange &EditRange,
-                                const SourceManager &SM,
-                                const LangOptions &LangOpts) {
-  // FIXME: makeFileCharRange() has the disadvantage of stripping off "identity"
-  // macros. For example, if we're looking to rewrite the int literal 3 to 6,
-  // and we have the following definition:
-  //    #define DO_NOTHING(x) x
-  // then
-  //    foo(DO_NOTHING(3))
-  // will be rewritten to
-  //    foo(6)
-  // rather than the arguably better
-  //    foo(DO_NOTHING(6))
-  // Decide whether the current behavior is desirable and modify if not.
-  CharSourceRange Range = Lexer::makeFileCharRange(EditRange, SM, LangOpts);
-  if (Range.isInvalid())
-    return None;
-
-  if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID())
-    return None;
-  if (SM.isInSystemHeader(Range.getBegin()) ||
-      SM.isInSystemHeader(Range.getEnd()))
-    return None;
-
-  std::pair<FileID, unsigned> BeginInfo = SM.getDecomposedLoc(Range.getBegin());
-  std::pair<FileID, unsigned> EndInfo = SM.getDecomposedLoc(Range.getEnd());
-  if (BeginInfo.first != EndInfo.first ||
-      BeginInfo.second > EndInfo.second)
-    return None;
-
-  return Range;
-}

Removed: cfe/trunk/lib/Tooling/Refactoring/SourceCodeBuilders.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/SourceCodeBuilders.cpp?rev=374270&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/SourceCodeBuilders.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/SourceCodeBuilders.cpp (removed)
@@ -1,160 +0,0 @@
-//===--- SourceCodeBuilder.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 "clang/Tooling/Refactoring/SourceCodeBuilders.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/Tooling/Refactoring/SourceCode.h"
-#include "llvm/ADT/Twine.h"
-#include <string>
-
-using namespace clang;
-using namespace tooling;
-
-const Expr *tooling::reallyIgnoreImplicit(const Expr &E) {
-  const Expr *Expr = E.IgnoreImplicit();
-  if (const auto *CE = dyn_cast<CXXConstructExpr>(Expr)) {
-    if (CE->getNumArgs() > 0 &&
-        CE->getArg(0)->getSourceRange() == Expr->getSourceRange())
-      return CE->getArg(0)->IgnoreImplicit();
-  }
-  return Expr;
-}
-
-bool tooling::mayEverNeedParens(const Expr &E) {
-  const Expr *Expr = reallyIgnoreImplicit(E);
-  // We always want parens around unary, binary, and ternary operators, because
-  // they are lower precedence.
-  if (isa<UnaryOperator>(Expr) || isa<BinaryOperator>(Expr) ||
-      isa<AbstractConditionalOperator>(Expr))
-    return true;
-
-  // We need parens around calls to all overloaded operators except: function
-  // calls, subscripts, and expressions that are already part of an (implicit)
-  // call to operator->. These latter are all in the same precedence level as
-  // dot/arrow and that level is left associative, so they don't need parens
-  // when appearing on the left.
-  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
-    return Op->getOperator() != OO_Call && Op->getOperator() != OO_Subscript &&
-           Op->getOperator() != OO_Arrow;
-
-  return false;
-}
-
-bool tooling::needParensAfterUnaryOperator(const Expr &E) {
-  const Expr *Expr = reallyIgnoreImplicit(E);
-  if (isa<BinaryOperator>(Expr) || isa<AbstractConditionalOperator>(Expr))
-    return true;
-
-  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
-    return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
-           Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
-           Op->getOperator() != OO_Subscript;
-
-  return false;
-}
-
-llvm::Optional<std::string> tooling::buildParens(const Expr &E,
-                                                 const ASTContext &Context) {
-  StringRef Text = getText(E, Context);
-  if (Text.empty())
-    return llvm::None;
-  if (mayEverNeedParens(E))
-    return ("(" + Text + ")").str();
-  return Text.str();
-}
-
-llvm::Optional<std::string>
-tooling::buildDereference(const Expr &E, const ASTContext &Context) {
-  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
-    if (Op->getOpcode() == UO_AddrOf) {
-      // Strip leading '&'.
-      StringRef Text =
-          getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
-      if (Text.empty())
-        return llvm::None;
-      return Text.str();
-    }
-
-  StringRef Text = getText(E, Context);
-  if (Text.empty())
-    return llvm::None;
-  // Add leading '*'.
-  if (needParensAfterUnaryOperator(E))
-    return ("*(" + Text + ")").str();
-  return ("*" + Text).str();
-}
-
-llvm::Optional<std::string> tooling::buildAddressOf(const Expr &E,
-                                                    const ASTContext &Context) {
-  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
-    if (Op->getOpcode() == UO_Deref) {
-      // Strip leading '*'.
-      StringRef Text =
-          getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
-      if (Text.empty())
-        return llvm::None;
-      return Text.str();
-    }
-  // Add leading '&'.
-  StringRef Text = getText(E, Context);
-  if (Text.empty())
-    return llvm::None;
-  if (needParensAfterUnaryOperator(E)) {
-    return ("&(" + Text + ")").str();
-  }
-  return ("&" + Text).str();
-}
-
-llvm::Optional<std::string> tooling::buildDot(const Expr &E,
-                                              const ASTContext &Context) {
-  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
-    if (Op->getOpcode() == UO_Deref) {
-      // Strip leading '*', add following '->'.
-      const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
-      StringRef DerefText = getText(*SubExpr, Context);
-      if (DerefText.empty())
-        return llvm::None;
-      if (needParensBeforeDotOrArrow(*SubExpr))
-        return ("(" + DerefText + ")->").str();
-      return (DerefText + "->").str();
-    }
-
-  // Add following '.'.
-  StringRef Text = getText(E, Context);
-  if (Text.empty())
-    return llvm::None;
-  if (needParensBeforeDotOrArrow(E)) {
-    return ("(" + Text + ").").str();
-  }
-  return (Text + ".").str();
-}
-
-llvm::Optional<std::string> tooling::buildArrow(const Expr &E,
-                                                const ASTContext &Context) {
-  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
-    if (Op->getOpcode() == UO_AddrOf) {
-      // Strip leading '&', add following '.'.
-      const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
-      StringRef DerefText = getText(*SubExpr, Context);
-      if (DerefText.empty())
-        return llvm::None;
-      if (needParensBeforeDotOrArrow(*SubExpr))
-        return ("(" + DerefText + ").").str();
-      return (DerefText + ".").str();
-    }
-
-  // Add following '->'.
-  StringRef Text = getText(E, Context);
-  if (Text.empty())
-    return llvm::None;
-  if (needParensBeforeDotOrArrow(E))
-    return ("(" + Text + ")->").str();
-  return (Text + "->").str();
-}

Removed: cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp?rev=374270&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/Stencil.cpp (removed)
@@ -1,369 +0,0 @@
-//===--- Stencil.cpp - Stencil implementation -------------------*- 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 "clang/Tooling/Refactoring/Stencil.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/Expr.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/Refactoring/SourceCode.h"
-#include "clang/Tooling/Refactoring/SourceCodeBuilders.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Errc.h"
-#include <atomic>
-#include <memory>
-#include <string>
-
-using namespace clang;
-using namespace tooling;
-
-using ast_matchers::MatchFinder;
-using ast_type_traits::DynTypedNode;
-using llvm::errc;
-using llvm::Error;
-using llvm::Expected;
-using llvm::StringError;
-
-// A down_cast function to safely down cast a StencilPartInterface to a subclass
-// D. Returns nullptr if P is not an instance of D.
-template <typename D> const D *down_cast(const StencilPartInterface *P) {
-  if (P == nullptr || D::typeId() != P->typeId())
-    return nullptr;
-  return static_cast<const D *>(P);
-}
-
-static llvm::Expected<DynTypedNode>
-getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) {
-  auto &NodesMap = Nodes.getMap();
-  auto It = NodesMap.find(Id);
-  if (It == NodesMap.end())
-    return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
-                                               "Id not bound: " + Id);
-  return It->second;
-}
-
-namespace {
-// An arbitrary fragment of code within a stencil.
-struct RawTextData {
-  explicit RawTextData(std::string T) : Text(std::move(T)) {}
-  std::string Text;
-};
-
-// A debugging operation to dump the AST for a particular (bound) AST node.
-struct DebugPrintNodeData {
-  explicit DebugPrintNodeData(std::string S) : Id(std::move(S)) {}
-  std::string Id;
-};
-
-// Operators that take a single node Id as an argument.
-enum class UnaryNodeOperator {
-  Parens,
-  Deref,
-  Address,
-};
-
-// Generic container for stencil operations with a (single) node-id argument.
-struct UnaryOperationData {
-  UnaryOperationData(UnaryNodeOperator Op, std::string Id)
-      : Op(Op), Id(std::move(Id)) {}
-  UnaryNodeOperator Op;
-  std::string Id;
-};
-
-// The fragment of code corresponding to the selected range.
-struct SelectorData {
-  explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {}
-  RangeSelector Selector;
-};
-
-// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
-struct AccessData {
-  AccessData(StringRef BaseId, StencilPart Member)
-      : BaseId(BaseId), Member(std::move(Member)) {}
-  std::string BaseId;
-  StencilPart Member;
-};
-
-struct IfBoundData {
-  IfBoundData(StringRef Id, StencilPart TruePart, StencilPart FalsePart)
-      : Id(Id), TruePart(std::move(TruePart)), FalsePart(std::move(FalsePart)) {
-  }
-  std::string Id;
-  StencilPart TruePart;
-  StencilPart FalsePart;
-};
-
-bool isEqualData(const RawTextData &A, const RawTextData &B) {
-  return A.Text == B.Text;
-}
-
-bool isEqualData(const DebugPrintNodeData &A, const DebugPrintNodeData &B) {
-  return A.Id == B.Id;
-}
-
-bool isEqualData(const UnaryOperationData &A, const UnaryOperationData &B) {
-  return A.Op == B.Op && A.Id == B.Id;
-}
-
-// Equality is not (yet) defined for \c RangeSelector.
-bool isEqualData(const SelectorData &, const SelectorData &) { return false; }
-
-bool isEqualData(const AccessData &A, const AccessData &B) {
-  return A.BaseId == B.BaseId && A.Member == B.Member;
-}
-
-bool isEqualData(const IfBoundData &A, const IfBoundData &B) {
-  return A.Id == B.Id && A.TruePart == B.TruePart && A.FalsePart == B.FalsePart;
-}
-
-// Equality is not defined over MatchConsumers, which are opaque.
-bool isEqualData(const MatchConsumer<std::string> &A,
-                 const MatchConsumer<std::string> &B) {
-  return false;
-}
-
-std::string toStringData(const RawTextData &Data) {
-  std::string Result;
-  llvm::raw_string_ostream OS(Result);
-  OS << "\"";
-  OS.write_escaped(Data.Text);
-  OS << "\"";
-  OS.flush();
-  return Result;
-}
-
-std::string toStringData(const DebugPrintNodeData &Data) {
-  return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
-}
-
-std::string toStringData(const UnaryOperationData &Data) {
-  StringRef OpName;
-  switch (Data.Op) {
-  case UnaryNodeOperator::Parens:
-    OpName = "expression";
-    break;
-  case UnaryNodeOperator::Deref:
-    OpName = "deref";
-    break;
-  case UnaryNodeOperator::Address:
-    OpName = "addressOf";
-    break;
-  }
-  return (OpName + "(\"" + Data.Id + "\")").str();
-}
-
-std::string toStringData(const SelectorData &) { return "SelectorData()"; }
-
-std::string toStringData(const AccessData &Data) {
-  return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
-          Data.Member.toString() + ")")
-      .str();
-}
-
-std::string toStringData(const IfBoundData &Data) {
-  return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
-          Data.TruePart.toString() + ", " + Data.FalsePart.toString() + ")")
-      .str();
-}
-
-std::string toStringData(const MatchConsumer<std::string> &) {
-  return "MatchConsumer<std::string>()";
-}
-
-// The `evalData()` overloads evaluate the given stencil data to a string, given
-// the match result, and append it to `Result`. We define an overload for each
-// type of stencil data.
-
-Error evalData(const RawTextData &Data, const MatchFinder::MatchResult &,
-               std::string *Result) {
-  Result->append(Data.Text);
-  return Error::success();
-}
-
-Error evalData(const DebugPrintNodeData &Data,
-               const MatchFinder::MatchResult &Match, std::string *Result) {
-  std::string Output;
-  llvm::raw_string_ostream Os(Output);
-  auto NodeOrErr = getNode(Match.Nodes, Data.Id);
-  if (auto Err = NodeOrErr.takeError())
-    return Err;
-  NodeOrErr->print(Os, PrintingPolicy(Match.Context->getLangOpts()));
-  *Result += Os.str();
-  return Error::success();
-}
-
-Error evalData(const UnaryOperationData &Data,
-               const MatchFinder::MatchResult &Match, std::string *Result) {
-  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.Id);
-  if (E == nullptr)
-    return llvm::make_error<StringError>(
-        errc::invalid_argument, "Id not bound or not Expr: " + Data.Id);
-  llvm::Optional<std::string> Source;
-  switch (Data.Op) {
-  case UnaryNodeOperator::Parens:
-    Source = buildParens(*E, *Match.Context);
-    break;
-  case UnaryNodeOperator::Deref:
-    Source = buildDereference(*E, *Match.Context);
-    break;
-  case UnaryNodeOperator::Address:
-    Source = buildAddressOf(*E, *Match.Context);
-    break;
-  }
-  if (!Source)
-    return llvm::make_error<StringError>(
-        errc::invalid_argument,
-        "Could not construct expression source from ID: " + Data.Id);
-  *Result += *Source;
-  return Error::success();
-}
-
-Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match,
-               std::string *Result) {
-  auto Range = Data.Selector(Match);
-  if (!Range)
-    return Range.takeError();
-  *Result += getText(*Range, *Match.Context);
-  return Error::success();
-}
-
-Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
-               std::string *Result) {
-  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.BaseId);
-  if (E == nullptr)
-    return llvm::make_error<StringError>(errc::invalid_argument,
-                                         "Id not bound: " + Data.BaseId);
-  if (!E->isImplicitCXXThis()) {
-    if (llvm::Optional<std::string> S = E->getType()->isAnyPointerType()
-                                            ? buildArrow(*E, *Match.Context)
-                                            : buildDot(*E, *Match.Context))
-      *Result += *S;
-    else
-      return llvm::make_error<StringError>(
-          errc::invalid_argument,
-          "Could not construct object text from ID: " + Data.BaseId);
-  }
-  return Data.Member.eval(Match, Result);
-}
-
-Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
-               std::string *Result) {
-  auto &M = Match.Nodes.getMap();
-  return (M.find(Data.Id) != M.end() ? Data.TruePart : Data.FalsePart)
-      .eval(Match, Result);
-}
-
-Error evalData(const MatchConsumer<std::string> &Fn,
-               const MatchFinder::MatchResult &Match, std::string *Result) {
-  Expected<std::string> Value = Fn(Match);
-  if (!Value)
-    return Value.takeError();
-  *Result += *Value;
-  return Error::success();
-}
-
-template <typename T>
-class StencilPartImpl : public StencilPartInterface {
-  T Data;
-
-public:
-  template <typename... Ps>
-  explicit StencilPartImpl(Ps &&... Args)
-      : StencilPartInterface(StencilPartImpl::typeId()),
-        Data(std::forward<Ps>(Args)...) {}
-
-  // Generates a unique identifier for this class (specifically, one per
-  // instantiation of the template).
-  static const void* typeId() {
-    static bool b;
-    return &b;
-  }
-
-  Error eval(const MatchFinder::MatchResult &Match,
-             std::string *Result) const override {
-    return evalData(Data, Match, Result);
-  }
-
-  bool isEqual(const StencilPartInterface &Other) const override {
-    if (const auto *OtherPtr = down_cast<StencilPartImpl>(&Other))
-      return isEqualData(Data, OtherPtr->Data);
-    return false;
-  }
-
-  std::string toString() const override { return toStringData(Data); }
-};
-} // namespace
-
-StencilPart Stencil::wrap(StringRef Text) {
-  return stencil::text(Text);
-}
-
-StencilPart Stencil::wrap(RangeSelector Selector) {
-  return stencil::selection(std::move(Selector));
-}
-
-void Stencil::append(Stencil OtherStencil) {
-  for (auto &Part : OtherStencil.Parts)
-    Parts.push_back(std::move(Part));
-}
-
-llvm::Expected<std::string>
-Stencil::eval(const MatchFinder::MatchResult &Match) const {
-  std::string Result;
-  for (const auto &Part : Parts)
-    if (auto Err = Part.eval(Match, &Result))
-      return std::move(Err);
-  return Result;
-}
-
-StencilPart stencil::text(StringRef Text) {
-  return StencilPart(std::make_shared<StencilPartImpl<RawTextData>>(Text));
-}
-
-StencilPart stencil::selection(RangeSelector Selector) {
-  return StencilPart(
-      std::make_shared<StencilPartImpl<SelectorData>>(std::move(Selector)));
-}
-
-StencilPart stencil::dPrint(StringRef Id) {
-  return StencilPart(std::make_shared<StencilPartImpl<DebugPrintNodeData>>(Id));
-}
-
-StencilPart stencil::expression(llvm::StringRef Id) {
-  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
-      UnaryNodeOperator::Parens, Id));
-}
-
-StencilPart stencil::deref(llvm::StringRef ExprId) {
-  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
-      UnaryNodeOperator::Deref, ExprId));
-}
-
-StencilPart stencil::addressOf(llvm::StringRef ExprId) {
-  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
-      UnaryNodeOperator::Address, ExprId));
-}
-
-StencilPart stencil::access(StringRef BaseId, StencilPart Member) {
-  return StencilPart(
-      std::make_shared<StencilPartImpl<AccessData>>(BaseId, std::move(Member)));
-}
-
-StencilPart stencil::ifBound(StringRef Id, StencilPart TruePart,
-                             StencilPart FalsePart) {
-  return StencilPart(std::make_shared<StencilPartImpl<IfBoundData>>(
-      Id, std::move(TruePart), std::move(FalsePart)));
-}
-
-StencilPart stencil::run(MatchConsumer<std::string> Fn) {
-  return StencilPart(
-      std::make_shared<StencilPartImpl<MatchConsumer<std::string>>>(
-          std::move(Fn)));
-}

Removed: cfe/trunk/lib/Tooling/Refactoring/Transformer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Refactoring/Transformer.cpp?rev=374270&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Refactoring/Transformer.cpp (original)
+++ cfe/trunk/lib/Tooling/Refactoring/Transformer.cpp (removed)
@@ -1,235 +0,0 @@
-//===--- Transformer.cpp - Transformer library implementation ---*- 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 "clang/Tooling/Refactoring/Transformer.h"
-#include "clang/AST/Expr.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "clang/Tooling/Refactoring/SourceCode.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-#include <string>
-#include <utility>
-#include <vector>
-#include <map>
-
-using namespace clang;
-using namespace tooling;
-
-using ast_matchers::MatchFinder;
-using ast_matchers::internal::DynTypedMatcher;
-using ast_type_traits::ASTNodeKind;
-using ast_type_traits::DynTypedNode;
-using llvm::Error;
-using llvm::StringError;
-
-using MatchResult = MatchFinder::MatchResult;
-
-Expected<SmallVector<tooling::detail::Transformation, 1>>
-tooling::detail::translateEdits(const MatchResult &Result,
-                                llvm::ArrayRef<ASTEdit> Edits) {
-  SmallVector<tooling::detail::Transformation, 1> Transformations;
-  for (const auto &Edit : Edits) {
-    Expected<CharSourceRange> Range = Edit.TargetRange(Result);
-    if (!Range)
-      return Range.takeError();
-    llvm::Optional<CharSourceRange> EditRange =
-        getRangeForEdit(*Range, *Result.Context);
-    // FIXME: let user specify whether to treat this case as an error or ignore
-    // it as is currently done.
-    if (!EditRange)
-      return SmallVector<Transformation, 0>();
-    auto Replacement = Edit.Replacement(Result);
-    if (!Replacement)
-      return Replacement.takeError();
-    tooling::detail::Transformation T;
-    T.Range = *EditRange;
-    T.Replacement = std::move(*Replacement);
-    Transformations.push_back(std::move(T));
-  }
-  return Transformations;
-}
-
-ASTEdit tooling::change(RangeSelector S, TextGenerator Replacement) {
-  ASTEdit E;
-  E.TargetRange = std::move(S);
-  E.Replacement = std::move(Replacement);
-  return E;
-}
-
-RewriteRule tooling::makeRule(DynTypedMatcher M, SmallVector<ASTEdit, 1> Edits,
-                              TextGenerator Explanation) {
-  return RewriteRule{{RewriteRule::Case{
-      std::move(M), std::move(Edits), std::move(Explanation), {}}}};
-}
-
-void tooling::addInclude(RewriteRule &Rule, StringRef Header,
-                         IncludeFormat Format) {
-  for (auto &Case : Rule.Cases)
-    Case.AddedIncludes.emplace_back(Header.str(), Format);
-}
-
-#ifndef NDEBUG
-// Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds
-// (all node matcher types except for `QualType` and `Type`), rather than just
-// banning `QualType` and `Type`.
-static bool hasValidKind(const DynTypedMatcher &M) {
-  return !M.canConvertTo<QualType>();
-}
-#endif
-
-// Binds each rule's matcher to a unique (and deterministic) tag based on
-// `TagBase` and the id paired with the case.
-static std::vector<DynTypedMatcher> taggedMatchers(
-    StringRef TagBase,
-    const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases) {
-  std::vector<DynTypedMatcher> Matchers;
-  Matchers.reserve(Cases.size());
-  for (const auto &Case : Cases) {
-    std::string Tag = (TagBase + Twine(Case.first)).str();
-    // HACK: Many matchers are not bindable, so ensure that tryBind will work.
-    DynTypedMatcher BoundMatcher(Case.second.Matcher);
-    BoundMatcher.setAllowBind(true);
-    auto M = BoundMatcher.tryBind(Tag);
-    Matchers.push_back(*std::move(M));
-  }
-  return Matchers;
-}
-
-// Simply gathers the contents of the various rules into a single rule. The
-// actual work to combine these into an ordered choice is deferred to matcher
-// registration.
-RewriteRule tooling::applyFirst(ArrayRef<RewriteRule> Rules) {
-  RewriteRule R;
-  for (auto &Rule : Rules)
-    R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
-  return R;
-}
-
-std::vector<DynTypedMatcher>
-tooling::detail::buildMatchers(const RewriteRule &Rule) {
-  // Map the cases into buckets of matchers -- one for each "root" AST kind,
-  // which guarantees that they can be combined in a single anyOf matcher. Each
-  // case is paired with an identifying number that is converted to a string id
-  // in `taggedMatchers`.
-  std::map<ASTNodeKind, SmallVector<std::pair<size_t, RewriteRule::Case>, 1>>
-      Buckets;
-  const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases;
-  for (int I = 0, N = Cases.size(); I < N; ++I) {
-    assert(hasValidKind(Cases[I].Matcher) &&
-           "Matcher must be non-(Qual)Type node matcher");
-    Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]);
-  }
-
-  std::vector<DynTypedMatcher> Matchers;
-  for (const auto &Bucket : Buckets) {
-    DynTypedMatcher M = DynTypedMatcher::constructVariadic(
-        DynTypedMatcher::VO_AnyOf, Bucket.first,
-        taggedMatchers("Tag", Bucket.second));
-    M.setAllowBind(true);
-    // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true.
-    Matchers.push_back(*M.tryBind(RewriteRule::RootID));
-  }
-  return Matchers;
-}
-
-DynTypedMatcher tooling::detail::buildMatcher(const RewriteRule &Rule) {
-  std::vector<DynTypedMatcher> Ms = buildMatchers(Rule);
-  assert(Ms.size() == 1 && "Cases must have compatible matchers.");
-  return Ms[0];
-}
-
-SourceLocation tooling::detail::getRuleMatchLoc(const MatchResult &Result) {
-  auto &NodesMap = Result.Nodes.getMap();
-  auto Root = NodesMap.find(RewriteRule::RootID);
-  assert(Root != NodesMap.end() && "Transformation failed: missing root node.");
-  llvm::Optional<CharSourceRange> RootRange = getRangeForEdit(
-      CharSourceRange::getTokenRange(Root->second.getSourceRange()),
-      *Result.Context);
-  if (RootRange)
-    return RootRange->getBegin();
-  // The match doesn't have a coherent range, so fall back to the expansion
-  // location as the "beginning" of the match.
-  return Result.SourceManager->getExpansionLoc(
-      Root->second.getSourceRange().getBegin());
-}
-
-// Finds the case that was "selected" -- that is, whose matcher triggered the
-// `MatchResult`.
-const RewriteRule::Case &
-tooling::detail::findSelectedCase(const MatchResult &Result,
-                                  const RewriteRule &Rule) {
-  if (Rule.Cases.size() == 1)
-    return Rule.Cases[0];
-
-  auto &NodesMap = Result.Nodes.getMap();
-  for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) {
-    std::string Tag = ("Tag" + Twine(i)).str();
-    if (NodesMap.find(Tag) != NodesMap.end())
-      return Rule.Cases[i];
-  }
-  llvm_unreachable("No tag found for this rule.");
-}
-
-constexpr llvm::StringLiteral RewriteRule::RootID;
-
-void Transformer::registerMatchers(MatchFinder *MatchFinder) {
-  for (auto &Matcher : tooling::detail::buildMatchers(Rule))
-    MatchFinder->addDynamicMatcher(Matcher, this);
-}
-
-void Transformer::run(const MatchResult &Result) {
-  if (Result.Context->getDiagnostics().hasErrorOccurred())
-    return;
-
-  RewriteRule::Case Case = tooling::detail::findSelectedCase(Result, Rule);
-  auto Transformations = tooling::detail::translateEdits(Result, Case.Edits);
-  if (!Transformations) {
-    Consumer(Transformations.takeError());
-    return;
-  }
-
-  if (Transformations->empty()) {
-    // No rewrite applied (but no error encountered either).
-    detail::getRuleMatchLoc(Result).print(
-        llvm::errs() << "note: skipping match at loc ", *Result.SourceManager);
-    llvm::errs() << "\n";
-    return;
-  }
-
-  // Record the results in the AtomicChange, anchored at the location of the
-  // first change.
-  AtomicChange AC(*Result.SourceManager,
-                  (*Transformations)[0].Range.getBegin());
-  for (const auto &T : *Transformations) {
-    if (auto Err = AC.replace(*Result.SourceManager, T.Range, T.Replacement)) {
-      Consumer(std::move(Err));
-      return;
-    }
-  }
-
-  for (const auto &I : Case.AddedIncludes) {
-    auto &Header = I.first;
-    switch (I.second) {
-    case IncludeFormat::Quoted:
-      AC.addHeader(Header);
-      break;
-    case IncludeFormat::Angled:
-      AC.addHeader((llvm::Twine("<") + Header + ">").str());
-      break;
-    }
-  }
-
-  Consumer(std::move(AC));
-}

Added: cfe/trunk/lib/Tooling/Transformer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/CMakeLists.txt?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/CMakeLists.txt (added)
+++ cfe/trunk/lib/Tooling/Transformer/CMakeLists.txt Wed Oct  9 19:34:47 2019
@@ -0,0 +1,17 @@
+set(LLVM_LINK_COMPONENTS Support)
+
+add_clang_library(clangTransformer
+  RangeSelector.cpp
+  SourceCode.cpp
+  SourceCodeBuilders.cpp
+  Stencil.cpp
+  Transformer.cpp
+
+  LINK_LIBS
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangLex
+  clangToolingCore
+  clangToolingRefactoring
+  )

Added: cfe/trunk/lib/Tooling/Transformer/RangeSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/RangeSelector.cpp?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/RangeSelector.cpp (added)
+++ cfe/trunk/lib/Tooling/Transformer/RangeSelector.cpp Wed Oct  9 19:34:47 2019
@@ -0,0 +1,312 @@
+//===--- RangeSelector.cpp - RangeSelector implementations ------*- 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 "clang/Tooling/Transformer/RangeSelector.h"
+#include "clang/AST/Expr.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace tooling;
+
+using ast_matchers::MatchFinder;
+using ast_type_traits::ASTNodeKind;
+using ast_type_traits::DynTypedNode;
+using llvm::Error;
+using llvm::StringError;
+
+using MatchResult = MatchFinder::MatchResult;
+
+static Error invalidArgumentError(Twine Message) {
+  return llvm::make_error<StringError>(llvm::errc::invalid_argument, Message);
+}
+
+static Error typeError(StringRef ID, const ASTNodeKind &Kind) {
+  return invalidArgumentError("mismatched type (node id=" + ID +
+                              " kind=" + Kind.asStringRef() + ")");
+}
+
+static Error typeError(StringRef ID, const ASTNodeKind &Kind,
+                       Twine ExpectedType) {
+  return invalidArgumentError("mismatched type: expected one of " +
+                              ExpectedType + " (node id=" + ID +
+                              " kind=" + Kind.asStringRef() + ")");
+}
+
+static Error missingPropertyError(StringRef ID, Twine Description,
+                                  StringRef Property) {
+  return invalidArgumentError(Description + " requires property '" + Property +
+                              "' (node id=" + ID + ")");
+}
+
+static Expected<DynTypedNode> getNode(const ast_matchers::BoundNodes &Nodes,
+                                      StringRef ID) {
+  auto &NodesMap = Nodes.getMap();
+  auto It = NodesMap.find(ID);
+  if (It == NodesMap.end())
+    return invalidArgumentError("ID not bound: " + ID);
+  return It->second;
+}
+
+// FIXME: handling of macros should be configurable.
+static SourceLocation findPreviousTokenStart(SourceLocation Start,
+                                             const SourceManager &SM,
+                                             const LangOptions &LangOpts) {
+  if (Start.isInvalid() || Start.isMacroID())
+    return SourceLocation();
+
+  SourceLocation BeforeStart = Start.getLocWithOffset(-1);
+  if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
+    return SourceLocation();
+
+  return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
+}
+
+// Finds the start location of the previous token of kind \p TK.
+// FIXME: handling of macros should be configurable.
+static SourceLocation findPreviousTokenKind(SourceLocation Start,
+                                            const SourceManager &SM,
+                                            const LangOptions &LangOpts,
+                                            tok::TokenKind TK) {
+  while (true) {
+    SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
+    if (L.isInvalid() || L.isMacroID())
+      return SourceLocation();
+
+    Token T;
+    if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
+      return SourceLocation();
+
+    if (T.is(TK))
+      return T.getLocation();
+
+    Start = L;
+  }
+}
+
+static SourceLocation findOpenParen(const CallExpr &E, const SourceManager &SM,
+                                    const LangOptions &LangOpts) {
+  SourceLocation EndLoc =
+      E.getNumArgs() == 0 ? E.getRParenLoc() : E.getArg(0)->getBeginLoc();
+  return findPreviousTokenKind(EndLoc, SM, LangOpts, tok::TokenKind::l_paren);
+}
+
+RangeSelector tooling::before(RangeSelector Selector) {
+  return [Selector](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<CharSourceRange> SelectedRange = Selector(Result);
+    if (!SelectedRange)
+      return SelectedRange.takeError();
+    return CharSourceRange::getCharRange(SelectedRange->getBegin());
+  };
+}
+
+RangeSelector tooling::after(RangeSelector Selector) {
+  return [Selector](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<CharSourceRange> SelectedRange = Selector(Result);
+    if (!SelectedRange)
+      return SelectedRange.takeError();
+    if (SelectedRange->isCharRange())
+      return CharSourceRange::getCharRange(SelectedRange->getEnd());
+    return CharSourceRange::getCharRange(Lexer::getLocForEndOfToken(
+        SelectedRange->getEnd(), 0, Result.Context->getSourceManager(),
+        Result.Context->getLangOpts()));
+  };
+}
+
+RangeSelector tooling::node(std::string ID) {
+  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
+    if (!Node)
+      return Node.takeError();
+    return Node->get<Stmt>() != nullptr && Node->get<Expr>() == nullptr
+               ? getExtendedRange(*Node, tok::TokenKind::semi, *Result.Context)
+               : CharSourceRange::getTokenRange(Node->getSourceRange());
+  };
+}
+
+RangeSelector tooling::statement(std::string ID) {
+  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
+    if (!Node)
+      return Node.takeError();
+    return getExtendedRange(*Node, tok::TokenKind::semi, *Result.Context);
+  };
+}
+
+RangeSelector tooling::range(RangeSelector Begin, RangeSelector End) {
+  return [Begin, End](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<CharSourceRange> BeginRange = Begin(Result);
+    if (!BeginRange)
+      return BeginRange.takeError();
+    Expected<CharSourceRange> EndRange = End(Result);
+    if (!EndRange)
+      return EndRange.takeError();
+    SourceLocation B = BeginRange->getBegin();
+    SourceLocation E = EndRange->getEnd();
+    // Note: we are precluding the possibility of sub-token ranges in the case
+    // that EndRange is a token range.
+    if (Result.SourceManager->isBeforeInTranslationUnit(E, B)) {
+      return invalidArgumentError("Bad range: out of order");
+    }
+    return CharSourceRange(SourceRange(B, E), EndRange->isTokenRange());
+  };
+}
+
+RangeSelector tooling::range(std::string BeginID, std::string EndID) {
+  return tooling::range(node(std::move(BeginID)), node(std::move(EndID)));
+}
+
+RangeSelector tooling::member(std::string ID) {
+  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<DynTypedNode> Node = getNode(Result.Nodes, ID);
+    if (!Node)
+      return Node.takeError();
+    if (auto *M = Node->get<clang::MemberExpr>())
+      return CharSourceRange::getTokenRange(
+          M->getMemberNameInfo().getSourceRange());
+    return typeError(ID, Node->getNodeKind(), "MemberExpr");
+  };
+}
+
+RangeSelector tooling::name(std::string ID) {
+  return [ID](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<DynTypedNode> N = getNode(Result.Nodes, ID);
+    if (!N)
+      return N.takeError();
+    auto &Node = *N;
+    if (const auto *D = Node.get<NamedDecl>()) {
+      if (!D->getDeclName().isIdentifier())
+        return missingPropertyError(ID, "name", "identifier");
+      SourceLocation L = D->getLocation();
+      auto R = CharSourceRange::getTokenRange(L, L);
+      // Verify that the range covers exactly the name.
+      // FIXME: extend this code to support cases like `operator +` or
+      // `foo<int>` for which this range will be too short.  Doing so will
+      // require subcasing `NamedDecl`, because it doesn't provide virtual
+      // access to the \c DeclarationNameInfo.
+      if (getText(R, *Result.Context) != D->getName())
+        return CharSourceRange();
+      return R;
+    }
+    if (const auto *E = Node.get<DeclRefExpr>()) {
+      if (!E->getNameInfo().getName().isIdentifier())
+        return missingPropertyError(ID, "name", "identifier");
+      SourceLocation L = E->getLocation();
+      return CharSourceRange::getTokenRange(L, L);
+    }
+    if (const auto *I = Node.get<CXXCtorInitializer>()) {
+      if (!I->isMemberInitializer() && I->isWritten())
+        return missingPropertyError(ID, "name", "explicit member initializer");
+      SourceLocation L = I->getMemberLocation();
+      return CharSourceRange::getTokenRange(L, L);
+    }
+    return typeError(ID, Node.getNodeKind(),
+                     "DeclRefExpr, NamedDecl, CXXCtorInitializer");
+  };
+}
+
+namespace {
+// FIXME: make this available in the public API for users to easily create their
+// own selectors.
+
+// Creates a selector from a range-selection function \p Func, which selects a
+// range that is relative to a bound node id.  \c T is the node type expected by
+// \p Func.
+template <typename T, CharSourceRange (*Func)(const MatchResult &, const T &)>
+class RelativeSelector {
+  std::string ID;
+
+public:
+  RelativeSelector(std::string ID) : ID(std::move(ID)) {}
+
+  Expected<CharSourceRange> operator()(const MatchResult &Result) {
+    Expected<DynTypedNode> N = getNode(Result.Nodes, ID);
+    if (!N)
+      return N.takeError();
+    if (const auto *Arg = N->get<T>())
+      return Func(Result, *Arg);
+    return typeError(ID, N->getNodeKind());
+  }
+};
+} // namespace
+
+// FIXME: Change the following functions from being in an anonymous namespace
+// to static functions, after the minimum Visual C++ has _MSC_VER >= 1915
+// (equivalent to Visual Studio 2017 v15.8 or higher). Using the anonymous
+// namespace works around a bug in earlier versions.
+namespace {
+// Returns the range of the statements (all source between the braces).
+CharSourceRange getStatementsRange(const MatchResult &,
+                                   const CompoundStmt &CS) {
+  return CharSourceRange::getCharRange(CS.getLBracLoc().getLocWithOffset(1),
+                                       CS.getRBracLoc());
+}
+} // namespace
+
+RangeSelector tooling::statements(std::string ID) {
+  return RelativeSelector<CompoundStmt, getStatementsRange>(std::move(ID));
+}
+
+namespace {
+// Returns the range of the source between the call's parentheses.
+CharSourceRange getCallArgumentsRange(const MatchResult &Result,
+                                      const CallExpr &CE) {
+  return CharSourceRange::getCharRange(
+      findOpenParen(CE, *Result.SourceManager, Result.Context->getLangOpts())
+          .getLocWithOffset(1),
+      CE.getRParenLoc());
+}
+} // namespace
+
+RangeSelector tooling::callArgs(std::string ID) {
+  return RelativeSelector<CallExpr, getCallArgumentsRange>(std::move(ID));
+}
+
+namespace {
+// Returns the range of the elements of the initializer list. Includes all
+// source between the braces.
+CharSourceRange getElementsRange(const MatchResult &,
+                                 const InitListExpr &E) {
+  return CharSourceRange::getCharRange(E.getLBraceLoc().getLocWithOffset(1),
+                                       E.getRBraceLoc());
+}
+} // namespace
+
+RangeSelector tooling::initListElements(std::string ID) {
+  return RelativeSelector<InitListExpr, getElementsRange>(std::move(ID));
+}
+
+namespace {
+// Returns the range of the else branch, including the `else` keyword.
+CharSourceRange getElseRange(const MatchResult &Result, const IfStmt &S) {
+  return maybeExtendRange(
+      CharSourceRange::getTokenRange(S.getElseLoc(), S.getEndLoc()),
+      tok::TokenKind::semi, *Result.Context);
+}
+} // namespace
+
+RangeSelector tooling::elseBranch(std::string ID) {
+  return RelativeSelector<IfStmt, getElseRange>(std::move(ID));
+}
+
+RangeSelector tooling::expansion(RangeSelector S) {
+  return [S](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<CharSourceRange> SRange = S(Result);
+    if (!SRange)
+      return SRange.takeError();
+    return Result.SourceManager->getExpansionRange(*SRange);
+  };
+}

Added: cfe/trunk/lib/Tooling/Transformer/SourceCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/SourceCode.cpp?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/SourceCode.cpp (added)
+++ cfe/trunk/lib/Tooling/Transformer/SourceCode.cpp Wed Oct  9 19:34:47 2019
@@ -0,0 +1,65 @@
+//===--- SourceCode.cpp - Source code manipulation routines -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file provides functions that simplify extraction of source code.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+
+StringRef clang::tooling::getText(CharSourceRange Range,
+                                  const ASTContext &Context) {
+  return Lexer::getSourceText(Range, Context.getSourceManager(),
+                              Context.getLangOpts());
+}
+
+CharSourceRange clang::tooling::maybeExtendRange(CharSourceRange Range,
+                                                 tok::TokenKind Next,
+                                                 ASTContext &Context) {
+  Optional<Token> Tok = Lexer::findNextToken(
+      Range.getEnd(), Context.getSourceManager(), Context.getLangOpts());
+  if (!Tok || !Tok->is(Next))
+    return Range;
+  return CharSourceRange::getTokenRange(Range.getBegin(), Tok->getLocation());
+}
+
+llvm::Optional<CharSourceRange>
+clang::tooling::getRangeForEdit(const CharSourceRange &EditRange,
+                                const SourceManager &SM,
+                                const LangOptions &LangOpts) {
+  // FIXME: makeFileCharRange() has the disadvantage of stripping off "identity"
+  // macros. For example, if we're looking to rewrite the int literal 3 to 6,
+  // and we have the following definition:
+  //    #define DO_NOTHING(x) x
+  // then
+  //    foo(DO_NOTHING(3))
+  // will be rewritten to
+  //    foo(6)
+  // rather than the arguably better
+  //    foo(DO_NOTHING(6))
+  // Decide whether the current behavior is desirable and modify if not.
+  CharSourceRange Range = Lexer::makeFileCharRange(EditRange, SM, LangOpts);
+  if (Range.isInvalid())
+    return None;
+
+  if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID())
+    return None;
+  if (SM.isInSystemHeader(Range.getBegin()) ||
+      SM.isInSystemHeader(Range.getEnd()))
+    return None;
+
+  std::pair<FileID, unsigned> BeginInfo = SM.getDecomposedLoc(Range.getBegin());
+  std::pair<FileID, unsigned> EndInfo = SM.getDecomposedLoc(Range.getEnd());
+  if (BeginInfo.first != EndInfo.first ||
+      BeginInfo.second > EndInfo.second)
+    return None;
+
+  return Range;
+}

Added: cfe/trunk/lib/Tooling/Transformer/SourceCodeBuilders.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/SourceCodeBuilders.cpp?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/SourceCodeBuilders.cpp (added)
+++ cfe/trunk/lib/Tooling/Transformer/SourceCodeBuilders.cpp Wed Oct  9 19:34:47 2019
@@ -0,0 +1,160 @@
+//===--- SourceCodeBuilder.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 "clang/Tooling/Transformer/SourceCodeBuilders.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "llvm/ADT/Twine.h"
+#include <string>
+
+using namespace clang;
+using namespace tooling;
+
+const Expr *tooling::reallyIgnoreImplicit(const Expr &E) {
+  const Expr *Expr = E.IgnoreImplicit();
+  if (const auto *CE = dyn_cast<CXXConstructExpr>(Expr)) {
+    if (CE->getNumArgs() > 0 &&
+        CE->getArg(0)->getSourceRange() == Expr->getSourceRange())
+      return CE->getArg(0)->IgnoreImplicit();
+  }
+  return Expr;
+}
+
+bool tooling::mayEverNeedParens(const Expr &E) {
+  const Expr *Expr = reallyIgnoreImplicit(E);
+  // We always want parens around unary, binary, and ternary operators, because
+  // they are lower precedence.
+  if (isa<UnaryOperator>(Expr) || isa<BinaryOperator>(Expr) ||
+      isa<AbstractConditionalOperator>(Expr))
+    return true;
+
+  // We need parens around calls to all overloaded operators except: function
+  // calls, subscripts, and expressions that are already part of an (implicit)
+  // call to operator->. These latter are all in the same precedence level as
+  // dot/arrow and that level is left associative, so they don't need parens
+  // when appearing on the left.
+  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
+    return Op->getOperator() != OO_Call && Op->getOperator() != OO_Subscript &&
+           Op->getOperator() != OO_Arrow;
+
+  return false;
+}
+
+bool tooling::needParensAfterUnaryOperator(const Expr &E) {
+  const Expr *Expr = reallyIgnoreImplicit(E);
+  if (isa<BinaryOperator>(Expr) || isa<AbstractConditionalOperator>(Expr))
+    return true;
+
+  if (const auto *Op = dyn_cast<CXXOperatorCallExpr>(Expr))
+    return Op->getNumArgs() == 2 && Op->getOperator() != OO_PlusPlus &&
+           Op->getOperator() != OO_MinusMinus && Op->getOperator() != OO_Call &&
+           Op->getOperator() != OO_Subscript;
+
+  return false;
+}
+
+llvm::Optional<std::string> tooling::buildParens(const Expr &E,
+                                                 const ASTContext &Context) {
+  StringRef Text = getText(E, Context);
+  if (Text.empty())
+    return llvm::None;
+  if (mayEverNeedParens(E))
+    return ("(" + Text + ")").str();
+  return Text.str();
+}
+
+llvm::Optional<std::string>
+tooling::buildDereference(const Expr &E, const ASTContext &Context) {
+  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&'.
+      StringRef Text =
+          getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
+      if (Text.empty())
+        return llvm::None;
+      return Text.str();
+    }
+
+  StringRef Text = getText(E, Context);
+  if (Text.empty())
+    return llvm::None;
+  // Add leading '*'.
+  if (needParensAfterUnaryOperator(E))
+    return ("*(" + Text + ")").str();
+  return ("*" + Text).str();
+}
+
+llvm::Optional<std::string> tooling::buildAddressOf(const Expr &E,
+                                                    const ASTContext &Context) {
+  if (const auto *Op = dyn_cast<UnaryOperator>(&E))
+    if (Op->getOpcode() == UO_Deref) {
+      // Strip leading '*'.
+      StringRef Text =
+          getText(*Op->getSubExpr()->IgnoreParenImpCasts(), Context);
+      if (Text.empty())
+        return llvm::None;
+      return Text.str();
+    }
+  // Add leading '&'.
+  StringRef Text = getText(E, Context);
+  if (Text.empty())
+    return llvm::None;
+  if (needParensAfterUnaryOperator(E)) {
+    return ("&(" + Text + ")").str();
+  }
+  return ("&" + Text).str();
+}
+
+llvm::Optional<std::string> tooling::buildDot(const Expr &E,
+                                              const ASTContext &Context) {
+  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
+    if (Op->getOpcode() == UO_Deref) {
+      // Strip leading '*', add following '->'.
+      const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
+      StringRef DerefText = getText(*SubExpr, Context);
+      if (DerefText.empty())
+        return llvm::None;
+      if (needParensBeforeDotOrArrow(*SubExpr))
+        return ("(" + DerefText + ")->").str();
+      return (DerefText + "->").str();
+    }
+
+  // Add following '.'.
+  StringRef Text = getText(E, Context);
+  if (Text.empty())
+    return llvm::None;
+  if (needParensBeforeDotOrArrow(E)) {
+    return ("(" + Text + ").").str();
+  }
+  return (Text + ".").str();
+}
+
+llvm::Optional<std::string> tooling::buildArrow(const Expr &E,
+                                                const ASTContext &Context) {
+  if (const auto *Op = llvm::dyn_cast<UnaryOperator>(&E))
+    if (Op->getOpcode() == UO_AddrOf) {
+      // Strip leading '&', add following '.'.
+      const Expr *SubExpr = Op->getSubExpr()->IgnoreParenImpCasts();
+      StringRef DerefText = getText(*SubExpr, Context);
+      if (DerefText.empty())
+        return llvm::None;
+      if (needParensBeforeDotOrArrow(*SubExpr))
+        return ("(" + DerefText + ").").str();
+      return (DerefText + ".").str();
+    }
+
+  // Add following '->'.
+  StringRef Text = getText(E, Context);
+  if (Text.empty())
+    return llvm::None;
+  if (needParensBeforeDotOrArrow(E))
+    return ("(" + Text + ")->").str();
+  return (Text + "->").str();
+}

Added: cfe/trunk/lib/Tooling/Transformer/Stencil.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/Stencil.cpp?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/Stencil.cpp (added)
+++ cfe/trunk/lib/Tooling/Transformer/Stencil.cpp Wed Oct  9 19:34:47 2019
@@ -0,0 +1,369 @@
+//===--- Stencil.cpp - Stencil implementation -------------------*- 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 "clang/Tooling/Transformer/Stencil.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Expr.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "clang/Tooling/Transformer/SourceCodeBuilders.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Errc.h"
+#include <atomic>
+#include <memory>
+#include <string>
+
+using namespace clang;
+using namespace tooling;
+
+using ast_matchers::MatchFinder;
+using ast_type_traits::DynTypedNode;
+using llvm::errc;
+using llvm::Error;
+using llvm::Expected;
+using llvm::StringError;
+
+// A down_cast function to safely down cast a StencilPartInterface to a subclass
+// D. Returns nullptr if P is not an instance of D.
+template <typename D> const D *down_cast(const StencilPartInterface *P) {
+  if (P == nullptr || D::typeId() != P->typeId())
+    return nullptr;
+  return static_cast<const D *>(P);
+}
+
+static llvm::Expected<DynTypedNode>
+getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) {
+  auto &NodesMap = Nodes.getMap();
+  auto It = NodesMap.find(Id);
+  if (It == NodesMap.end())
+    return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
+                                               "Id not bound: " + Id);
+  return It->second;
+}
+
+namespace {
+// An arbitrary fragment of code within a stencil.
+struct RawTextData {
+  explicit RawTextData(std::string T) : Text(std::move(T)) {}
+  std::string Text;
+};
+
+// A debugging operation to dump the AST for a particular (bound) AST node.
+struct DebugPrintNodeData {
+  explicit DebugPrintNodeData(std::string S) : Id(std::move(S)) {}
+  std::string Id;
+};
+
+// Operators that take a single node Id as an argument.
+enum class UnaryNodeOperator {
+  Parens,
+  Deref,
+  Address,
+};
+
+// Generic container for stencil operations with a (single) node-id argument.
+struct UnaryOperationData {
+  UnaryOperationData(UnaryNodeOperator Op, std::string Id)
+      : Op(Op), Id(std::move(Id)) {}
+  UnaryNodeOperator Op;
+  std::string Id;
+};
+
+// The fragment of code corresponding to the selected range.
+struct SelectorData {
+  explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {}
+  RangeSelector Selector;
+};
+
+// A stencil operation to build a member access `e.m` or `e->m`, as appropriate.
+struct AccessData {
+  AccessData(StringRef BaseId, StencilPart Member)
+      : BaseId(BaseId), Member(std::move(Member)) {}
+  std::string BaseId;
+  StencilPart Member;
+};
+
+struct IfBoundData {
+  IfBoundData(StringRef Id, StencilPart TruePart, StencilPart FalsePart)
+      : Id(Id), TruePart(std::move(TruePart)), FalsePart(std::move(FalsePart)) {
+  }
+  std::string Id;
+  StencilPart TruePart;
+  StencilPart FalsePart;
+};
+
+bool isEqualData(const RawTextData &A, const RawTextData &B) {
+  return A.Text == B.Text;
+}
+
+bool isEqualData(const DebugPrintNodeData &A, const DebugPrintNodeData &B) {
+  return A.Id == B.Id;
+}
+
+bool isEqualData(const UnaryOperationData &A, const UnaryOperationData &B) {
+  return A.Op == B.Op && A.Id == B.Id;
+}
+
+// Equality is not (yet) defined for \c RangeSelector.
+bool isEqualData(const SelectorData &, const SelectorData &) { return false; }
+
+bool isEqualData(const AccessData &A, const AccessData &B) {
+  return A.BaseId == B.BaseId && A.Member == B.Member;
+}
+
+bool isEqualData(const IfBoundData &A, const IfBoundData &B) {
+  return A.Id == B.Id && A.TruePart == B.TruePart && A.FalsePart == B.FalsePart;
+}
+
+// Equality is not defined over MatchConsumers, which are opaque.
+bool isEqualData(const MatchConsumer<std::string> &A,
+                 const MatchConsumer<std::string> &B) {
+  return false;
+}
+
+std::string toStringData(const RawTextData &Data) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << "\"";
+  OS.write_escaped(Data.Text);
+  OS << "\"";
+  OS.flush();
+  return Result;
+}
+
+std::string toStringData(const DebugPrintNodeData &Data) {
+  return (llvm::Twine("dPrint(\"") + Data.Id + "\")").str();
+}
+
+std::string toStringData(const UnaryOperationData &Data) {
+  StringRef OpName;
+  switch (Data.Op) {
+  case UnaryNodeOperator::Parens:
+    OpName = "expression";
+    break;
+  case UnaryNodeOperator::Deref:
+    OpName = "deref";
+    break;
+  case UnaryNodeOperator::Address:
+    OpName = "addressOf";
+    break;
+  }
+  return (OpName + "(\"" + Data.Id + "\")").str();
+}
+
+std::string toStringData(const SelectorData &) { return "SelectorData()"; }
+
+std::string toStringData(const AccessData &Data) {
+  return (llvm::Twine("access(\"") + Data.BaseId + "\", " +
+          Data.Member.toString() + ")")
+      .str();
+}
+
+std::string toStringData(const IfBoundData &Data) {
+  return (llvm::Twine("ifBound(\"") + Data.Id + "\", " +
+          Data.TruePart.toString() + ", " + Data.FalsePart.toString() + ")")
+      .str();
+}
+
+std::string toStringData(const MatchConsumer<std::string> &) {
+  return "MatchConsumer<std::string>()";
+}
+
+// The `evalData()` overloads evaluate the given stencil data to a string, given
+// the match result, and append it to `Result`. We define an overload for each
+// type of stencil data.
+
+Error evalData(const RawTextData &Data, const MatchFinder::MatchResult &,
+               std::string *Result) {
+  Result->append(Data.Text);
+  return Error::success();
+}
+
+Error evalData(const DebugPrintNodeData &Data,
+               const MatchFinder::MatchResult &Match, std::string *Result) {
+  std::string Output;
+  llvm::raw_string_ostream Os(Output);
+  auto NodeOrErr = getNode(Match.Nodes, Data.Id);
+  if (auto Err = NodeOrErr.takeError())
+    return Err;
+  NodeOrErr->print(Os, PrintingPolicy(Match.Context->getLangOpts()));
+  *Result += Os.str();
+  return Error::success();
+}
+
+Error evalData(const UnaryOperationData &Data,
+               const MatchFinder::MatchResult &Match, std::string *Result) {
+  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.Id);
+  if (E == nullptr)
+    return llvm::make_error<StringError>(
+        errc::invalid_argument, "Id not bound or not Expr: " + Data.Id);
+  llvm::Optional<std::string> Source;
+  switch (Data.Op) {
+  case UnaryNodeOperator::Parens:
+    Source = buildParens(*E, *Match.Context);
+    break;
+  case UnaryNodeOperator::Deref:
+    Source = buildDereference(*E, *Match.Context);
+    break;
+  case UnaryNodeOperator::Address:
+    Source = buildAddressOf(*E, *Match.Context);
+    break;
+  }
+  if (!Source)
+    return llvm::make_error<StringError>(
+        errc::invalid_argument,
+        "Could not construct expression source from ID: " + Data.Id);
+  *Result += *Source;
+  return Error::success();
+}
+
+Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match,
+               std::string *Result) {
+  auto Range = Data.Selector(Match);
+  if (!Range)
+    return Range.takeError();
+  *Result += getText(*Range, *Match.Context);
+  return Error::success();
+}
+
+Error evalData(const AccessData &Data, const MatchFinder::MatchResult &Match,
+               std::string *Result) {
+  const auto *E = Match.Nodes.getNodeAs<Expr>(Data.BaseId);
+  if (E == nullptr)
+    return llvm::make_error<StringError>(errc::invalid_argument,
+                                         "Id not bound: " + Data.BaseId);
+  if (!E->isImplicitCXXThis()) {
+    if (llvm::Optional<std::string> S = E->getType()->isAnyPointerType()
+                                            ? buildArrow(*E, *Match.Context)
+                                            : buildDot(*E, *Match.Context))
+      *Result += *S;
+    else
+      return llvm::make_error<StringError>(
+          errc::invalid_argument,
+          "Could not construct object text from ID: " + Data.BaseId);
+  }
+  return Data.Member.eval(Match, Result);
+}
+
+Error evalData(const IfBoundData &Data, const MatchFinder::MatchResult &Match,
+               std::string *Result) {
+  auto &M = Match.Nodes.getMap();
+  return (M.find(Data.Id) != M.end() ? Data.TruePart : Data.FalsePart)
+      .eval(Match, Result);
+}
+
+Error evalData(const MatchConsumer<std::string> &Fn,
+               const MatchFinder::MatchResult &Match, std::string *Result) {
+  Expected<std::string> Value = Fn(Match);
+  if (!Value)
+    return Value.takeError();
+  *Result += *Value;
+  return Error::success();
+}
+
+template <typename T>
+class StencilPartImpl : public StencilPartInterface {
+  T Data;
+
+public:
+  template <typename... Ps>
+  explicit StencilPartImpl(Ps &&... Args)
+      : StencilPartInterface(StencilPartImpl::typeId()),
+        Data(std::forward<Ps>(Args)...) {}
+
+  // Generates a unique identifier for this class (specifically, one per
+  // instantiation of the template).
+  static const void* typeId() {
+    static bool b;
+    return &b;
+  }
+
+  Error eval(const MatchFinder::MatchResult &Match,
+             std::string *Result) const override {
+    return evalData(Data, Match, Result);
+  }
+
+  bool isEqual(const StencilPartInterface &Other) const override {
+    if (const auto *OtherPtr = down_cast<StencilPartImpl>(&Other))
+      return isEqualData(Data, OtherPtr->Data);
+    return false;
+  }
+
+  std::string toString() const override { return toStringData(Data); }
+};
+} // namespace
+
+StencilPart Stencil::wrap(StringRef Text) {
+  return stencil::text(Text);
+}
+
+StencilPart Stencil::wrap(RangeSelector Selector) {
+  return stencil::selection(std::move(Selector));
+}
+
+void Stencil::append(Stencil OtherStencil) {
+  for (auto &Part : OtherStencil.Parts)
+    Parts.push_back(std::move(Part));
+}
+
+llvm::Expected<std::string>
+Stencil::eval(const MatchFinder::MatchResult &Match) const {
+  std::string Result;
+  for (const auto &Part : Parts)
+    if (auto Err = Part.eval(Match, &Result))
+      return std::move(Err);
+  return Result;
+}
+
+StencilPart stencil::text(StringRef Text) {
+  return StencilPart(std::make_shared<StencilPartImpl<RawTextData>>(Text));
+}
+
+StencilPart stencil::selection(RangeSelector Selector) {
+  return StencilPart(
+      std::make_shared<StencilPartImpl<SelectorData>>(std::move(Selector)));
+}
+
+StencilPart stencil::dPrint(StringRef Id) {
+  return StencilPart(std::make_shared<StencilPartImpl<DebugPrintNodeData>>(Id));
+}
+
+StencilPart stencil::expression(llvm::StringRef Id) {
+  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
+      UnaryNodeOperator::Parens, Id));
+}
+
+StencilPart stencil::deref(llvm::StringRef ExprId) {
+  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
+      UnaryNodeOperator::Deref, ExprId));
+}
+
+StencilPart stencil::addressOf(llvm::StringRef ExprId) {
+  return StencilPart(std::make_shared<StencilPartImpl<UnaryOperationData>>(
+      UnaryNodeOperator::Address, ExprId));
+}
+
+StencilPart stencil::access(StringRef BaseId, StencilPart Member) {
+  return StencilPart(
+      std::make_shared<StencilPartImpl<AccessData>>(BaseId, std::move(Member)));
+}
+
+StencilPart stencil::ifBound(StringRef Id, StencilPart TruePart,
+                             StencilPart FalsePart) {
+  return StencilPart(std::make_shared<StencilPartImpl<IfBoundData>>(
+      Id, std::move(TruePart), std::move(FalsePart)));
+}
+
+StencilPart stencil::run(MatchConsumer<std::string> Fn) {
+  return StencilPart(
+      std::make_shared<StencilPartImpl<MatchConsumer<std::string>>>(
+          std::move(Fn)));
+}

Added: cfe/trunk/lib/Tooling/Transformer/Transformer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/Transformer/Transformer.cpp?rev=374271&view=auto
==============================================================================
--- cfe/trunk/lib/Tooling/Transformer/Transformer.cpp (added)
+++ cfe/trunk/lib/Tooling/Transformer/Transformer.cpp Wed Oct  9 19:34:47 2019
@@ -0,0 +1,235 @@
+//===--- Transformer.cpp - Transformer library implementation ---*- 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 "clang/Tooling/Transformer/Transformer.h"
+#include "clang/AST/Expr.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Rewrite/Core/Rewriter.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace tooling;
+
+using ast_matchers::MatchFinder;
+using ast_matchers::internal::DynTypedMatcher;
+using ast_type_traits::ASTNodeKind;
+using ast_type_traits::DynTypedNode;
+using llvm::Error;
+using llvm::StringError;
+
+using MatchResult = MatchFinder::MatchResult;
+
+Expected<SmallVector<tooling::detail::Transformation, 1>>
+tooling::detail::translateEdits(const MatchResult &Result,
+                                llvm::ArrayRef<ASTEdit> Edits) {
+  SmallVector<tooling::detail::Transformation, 1> Transformations;
+  for (const auto &Edit : Edits) {
+    Expected<CharSourceRange> Range = Edit.TargetRange(Result);
+    if (!Range)
+      return Range.takeError();
+    llvm::Optional<CharSourceRange> EditRange =
+        getRangeForEdit(*Range, *Result.Context);
+    // FIXME: let user specify whether to treat this case as an error or ignore
+    // it as is currently done.
+    if (!EditRange)
+      return SmallVector<Transformation, 0>();
+    auto Replacement = Edit.Replacement(Result);
+    if (!Replacement)
+      return Replacement.takeError();
+    tooling::detail::Transformation T;
+    T.Range = *EditRange;
+    T.Replacement = std::move(*Replacement);
+    Transformations.push_back(std::move(T));
+  }
+  return Transformations;
+}
+
+ASTEdit tooling::change(RangeSelector S, TextGenerator Replacement) {
+  ASTEdit E;
+  E.TargetRange = std::move(S);
+  E.Replacement = std::move(Replacement);
+  return E;
+}
+
+RewriteRule tooling::makeRule(DynTypedMatcher M, SmallVector<ASTEdit, 1> Edits,
+                              TextGenerator Explanation) {
+  return RewriteRule{{RewriteRule::Case{
+      std::move(M), std::move(Edits), std::move(Explanation), {}}}};
+}
+
+void tooling::addInclude(RewriteRule &Rule, StringRef Header,
+                         IncludeFormat Format) {
+  for (auto &Case : Rule.Cases)
+    Case.AddedIncludes.emplace_back(Header.str(), Format);
+}
+
+#ifndef NDEBUG
+// Filters for supported matcher kinds. FIXME: Explicitly list the allowed kinds
+// (all node matcher types except for `QualType` and `Type`), rather than just
+// banning `QualType` and `Type`.
+static bool hasValidKind(const DynTypedMatcher &M) {
+  return !M.canConvertTo<QualType>();
+}
+#endif
+
+// Binds each rule's matcher to a unique (and deterministic) tag based on
+// `TagBase` and the id paired with the case.
+static std::vector<DynTypedMatcher> taggedMatchers(
+    StringRef TagBase,
+    const SmallVectorImpl<std::pair<size_t, RewriteRule::Case>> &Cases) {
+  std::vector<DynTypedMatcher> Matchers;
+  Matchers.reserve(Cases.size());
+  for (const auto &Case : Cases) {
+    std::string Tag = (TagBase + Twine(Case.first)).str();
+    // HACK: Many matchers are not bindable, so ensure that tryBind will work.
+    DynTypedMatcher BoundMatcher(Case.second.Matcher);
+    BoundMatcher.setAllowBind(true);
+    auto M = BoundMatcher.tryBind(Tag);
+    Matchers.push_back(*std::move(M));
+  }
+  return Matchers;
+}
+
+// Simply gathers the contents of the various rules into a single rule. The
+// actual work to combine these into an ordered choice is deferred to matcher
+// registration.
+RewriteRule tooling::applyFirst(ArrayRef<RewriteRule> Rules) {
+  RewriteRule R;
+  for (auto &Rule : Rules)
+    R.Cases.append(Rule.Cases.begin(), Rule.Cases.end());
+  return R;
+}
+
+std::vector<DynTypedMatcher>
+tooling::detail::buildMatchers(const RewriteRule &Rule) {
+  // Map the cases into buckets of matchers -- one for each "root" AST kind,
+  // which guarantees that they can be combined in a single anyOf matcher. Each
+  // case is paired with an identifying number that is converted to a string id
+  // in `taggedMatchers`.
+  std::map<ASTNodeKind, SmallVector<std::pair<size_t, RewriteRule::Case>, 1>>
+      Buckets;
+  const SmallVectorImpl<RewriteRule::Case> &Cases = Rule.Cases;
+  for (int I = 0, N = Cases.size(); I < N; ++I) {
+    assert(hasValidKind(Cases[I].Matcher) &&
+           "Matcher must be non-(Qual)Type node matcher");
+    Buckets[Cases[I].Matcher.getSupportedKind()].emplace_back(I, Cases[I]);
+  }
+
+  std::vector<DynTypedMatcher> Matchers;
+  for (const auto &Bucket : Buckets) {
+    DynTypedMatcher M = DynTypedMatcher::constructVariadic(
+        DynTypedMatcher::VO_AnyOf, Bucket.first,
+        taggedMatchers("Tag", Bucket.second));
+    M.setAllowBind(true);
+    // `tryBind` is guaranteed to succeed, because `AllowBind` was set to true.
+    Matchers.push_back(*M.tryBind(RewriteRule::RootID));
+  }
+  return Matchers;
+}
+
+DynTypedMatcher tooling::detail::buildMatcher(const RewriteRule &Rule) {
+  std::vector<DynTypedMatcher> Ms = buildMatchers(Rule);
+  assert(Ms.size() == 1 && "Cases must have compatible matchers.");
+  return Ms[0];
+}
+
+SourceLocation tooling::detail::getRuleMatchLoc(const MatchResult &Result) {
+  auto &NodesMap = Result.Nodes.getMap();
+  auto Root = NodesMap.find(RewriteRule::RootID);
+  assert(Root != NodesMap.end() && "Transformation failed: missing root node.");
+  llvm::Optional<CharSourceRange> RootRange = getRangeForEdit(
+      CharSourceRange::getTokenRange(Root->second.getSourceRange()),
+      *Result.Context);
+  if (RootRange)
+    return RootRange->getBegin();
+  // The match doesn't have a coherent range, so fall back to the expansion
+  // location as the "beginning" of the match.
+  return Result.SourceManager->getExpansionLoc(
+      Root->second.getSourceRange().getBegin());
+}
+
+// Finds the case that was "selected" -- that is, whose matcher triggered the
+// `MatchResult`.
+const RewriteRule::Case &
+tooling::detail::findSelectedCase(const MatchResult &Result,
+                                  const RewriteRule &Rule) {
+  if (Rule.Cases.size() == 1)
+    return Rule.Cases[0];
+
+  auto &NodesMap = Result.Nodes.getMap();
+  for (size_t i = 0, N = Rule.Cases.size(); i < N; ++i) {
+    std::string Tag = ("Tag" + Twine(i)).str();
+    if (NodesMap.find(Tag) != NodesMap.end())
+      return Rule.Cases[i];
+  }
+  llvm_unreachable("No tag found for this rule.");
+}
+
+constexpr llvm::StringLiteral RewriteRule::RootID;
+
+void Transformer::registerMatchers(MatchFinder *MatchFinder) {
+  for (auto &Matcher : tooling::detail::buildMatchers(Rule))
+    MatchFinder->addDynamicMatcher(Matcher, this);
+}
+
+void Transformer::run(const MatchResult &Result) {
+  if (Result.Context->getDiagnostics().hasErrorOccurred())
+    return;
+
+  RewriteRule::Case Case = tooling::detail::findSelectedCase(Result, Rule);
+  auto Transformations = tooling::detail::translateEdits(Result, Case.Edits);
+  if (!Transformations) {
+    Consumer(Transformations.takeError());
+    return;
+  }
+
+  if (Transformations->empty()) {
+    // No rewrite applied (but no error encountered either).
+    detail::getRuleMatchLoc(Result).print(
+        llvm::errs() << "note: skipping match at loc ", *Result.SourceManager);
+    llvm::errs() << "\n";
+    return;
+  }
+
+  // Record the results in the AtomicChange, anchored at the location of the
+  // first change.
+  AtomicChange AC(*Result.SourceManager,
+                  (*Transformations)[0].Range.getBegin());
+  for (const auto &T : *Transformations) {
+    if (auto Err = AC.replace(*Result.SourceManager, T.Range, T.Replacement)) {
+      Consumer(std::move(Err));
+      return;
+    }
+  }
+
+  for (const auto &I : Case.AddedIncludes) {
+    auto &Header = I.first;
+    switch (I.second) {
+    case IncludeFormat::Quoted:
+      AC.addHeader(Header);
+      break;
+    case IncludeFormat::Angled:
+      AC.addHeader((llvm::Twine("<") + Header + ">").str());
+      break;
+    }
+  }
+
+  Consumer(std::move(AC));
+}

Modified: cfe/trunk/unittests/Tooling/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CMakeLists.txt?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/CMakeLists.txt (original)
+++ cfe/trunk/unittests/Tooling/CMakeLists.txt Wed Oct  9 19:34:47 2019
@@ -75,6 +75,7 @@ clang_target_link_libraries(ToolingTests
   clangToolingCore
   clangToolingInclusions
   clangToolingRefactoring
+  clangTransformer
   )
 
 target_link_libraries(ToolingTests

Modified: cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/RangeSelectorTest.cpp Wed Oct  9 19:34:47 2019
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Refactoring/RangeSelector.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Tooling/FixIt.h"

Modified: cfe/trunk/unittests/Tooling/SourceCodeBuildersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/SourceCodeBuildersTest.cpp?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/SourceCodeBuildersTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/SourceCodeBuildersTest.cpp Wed Oct  9 19:34:47 2019
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Refactoring/SourceCodeBuilders.h"
+#include "clang/Tooling/Transformer/SourceCodeBuilders.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/Tooling.h"

Modified: cfe/trunk/unittests/Tooling/SourceCodeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/SourceCodeTest.cpp?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/SourceCodeTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/SourceCodeTest.cpp Wed Oct  9 19:34:47 2019
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Refactoring/SourceCode.h"
+#include "clang/Tooling/Transformer/SourceCode.h"
 #include "TestVisitor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/Testing/Support/Annotations.h"

Modified: cfe/trunk/unittests/Tooling/StencilTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/StencilTest.cpp?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/StencilTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/StencilTest.cpp Wed Oct  9 19:34:47 2019
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Refactoring/Stencil.h"
+#include "clang/Tooling/Transformer/Stencil.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
 #include "clang/Tooling/Tooling.h"

Modified: cfe/trunk/unittests/Tooling/TransformerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/TransformerTest.cpp?rev=374271&r1=374270&r2=374271&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/TransformerTest.cpp (original)
+++ cfe/trunk/unittests/Tooling/TransformerTest.cpp Wed Oct  9 19:34:47 2019
@@ -6,9 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Tooling/Refactoring/Transformer.h"
+#include "clang/Tooling/Transformer/Transformer.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Tooling/Refactoring/RangeSelector.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"




More information about the cfe-commits mailing list