Parcourir la source

Remove legacy migration prototype (#4887)

Although migration tooling is intended for Carbon, this tooling was
primarily a proof-of-concept prototype. The last time it got significant
work was in 2022
(https://github.com/carbon-language/carbon-lang/commits/trunk/migrate_cpp);
since then, we've mainly been doing small cleanups to keep it building.
We're now hitting an issue in #4886 that `TypeNodes.inc` isn't exposed
as a `#include`.

We already had thoughts about rewriting this as a `RecursiveASTVisitor`,
per `rewriter.cpp`/`rewriter.h`. That may justify a significantly
different approach than had been set up in `cpp_refactoring`. But, it's
hard to tell.

Either way, my sense is that rather than incrementally trying to keep
this code building, we should revisit it when we're ready and have a
long-term strategy for how migration should work.
Jon Ross-Perkins il y a 1 an
Parent
commit
a8aca3ce71

+ 0 - 2
bazel/check_deps/BUILD

@@ -15,8 +15,6 @@ filegroup(
     data = [
         "//explorer",
         "//installers/local:carbon",
-        "//migrate_cpp:rewriter",
-        "//migrate_cpp/cpp_refactoring",
         "//toolchain/install:carbon-busybox",
         # The tree sitter rules can't be queried; evaluation fails on
         # @platforms.

+ 0 - 60
migrate_cpp/BUILD

@@ -1,60 +0,0 @@
-# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-# Exceptions. See /LICENSE for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
-load("@rules_python//python:defs.bzl", "py_binary")
-
-py_binary(
-    name = "migrate_cpp",
-    srcs = ["migrate_cpp.py"],
-    data = [
-        ":clang_tidy.yaml",
-        "//migrate_cpp/cpp_refactoring",
-    ],
-    python_version = "PY3",
-)
-
-cc_library(
-    name = "output_segment",
-    hdrs = ["output_segment.h"],
-    deps = [
-        "//common:check",
-        "@llvm-project//clang:ast",
-    ],
-)
-
-cc_library(
-    name = "rewriter",
-    srcs = ["rewriter.cpp"],
-    hdrs = ["rewriter.h"],
-    visibility = [
-        # For dependency checking. Remove once it has a binary using it.
-        "//bazel/check_deps:__pkg__",
-    ],
-    deps = [
-        ":output_segment",
-        "//common:check",
-        "@llvm-project//clang:ast",
-        "@llvm-project//clang:basic",
-        "@llvm-project//clang:frontend",
-        "@llvm-project//clang:lex",
-        "@llvm-project//clang:tooling",
-        "@llvm-project//clang:tooling_core",
-        "@llvm-project//llvm:Support",
-    ],
-)
-
-cc_test(
-    name = "rewriter_test",
-    size = "small",
-    srcs = ["rewriter_test.cpp"],
-    deps = [
-        ":rewriter",
-        "//testing/base:gtest_main",
-        "@googletest//:gtest",
-        "@llvm-project//clang:ast",
-        "@llvm-project//clang:frontend",
-        "@llvm-project//clang:tooling",
-    ],
-)

+ 0 - 28
migrate_cpp/README.md

@@ -1,28 +0,0 @@
-# C++ migration tooling
-
-<!--
-Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-Exceptions. See /LICENSE for license information.
-SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--->
-
-<!-- toc -->
-
-## Table of contents
-
--   [Overview](#overview)
--   [Structure](#structure)
-
-<!-- tocstop -->
-
-## Overview
-
-`migrate_cpp` assists in migration of C++ code to Carbon. It's currently being
-assembled; more documentation will be added later.
-
-## Structure
-
-The `migrate_cpp` tool uses a `clang::RecursiveASTVisitor` to traverse Clang's
-AST and, to each node, associate replacements. Each node's replacement is a
-sequence of text, or a reference to some other node that should be used to
-replace it.

+ 0 - 16
migrate_cpp/clang_tidy.yaml

@@ -1,16 +0,0 @@
-# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-# Exceptions. See /LICENSE for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-# Use clang-tidy to standardize syntax. This configuration focuses on
-# modernizations, not casing-related choices, in order to avoid changes which
-# would affect non-migrated callers.
-
----
-Checks:
-  -*, bugprone-*, -bugprone-reserved-identifier, google-*,
-  -google-readability-todo, misc-definitions-in-headers, misc-misplaced-const,
-  misc-redundant-expression, misc-static-assert,
-  misc-unconventional-assign-operator, misc-uniqueptr-reset-release,
-  misc-unused-*, modernize-*, -modernize-avoid-c-arrays, performance-*,
-  readability-braces-around-statements

+ 0 - 120
migrate_cpp/cpp_refactoring/BUILD

@@ -1,120 +0,0 @@
-# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-# Exceptions. See /LICENSE for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
-
-package(default_visibility = ["//visibility:public"])
-
-cc_binary(
-    name = "cpp_refactoring",
-    srcs = ["main.cpp"],
-    deps = [
-        ":fn_inserter",
-        ":for_range",
-        ":matcher",
-        ":var_decl",
-        "@llvm-project//clang:tooling",
-    ],
-)
-
-cc_library(
-    name = "matcher",
-    srcs = ["matcher.cpp"],
-    hdrs = [
-        "matcher.h",
-        "matcher_manager.h",
-    ],
-    deps = [
-        "@llvm-project//clang:ast_matchers",
-        "@llvm-project//clang:basic",
-        "@llvm-project//clang:lex",
-        "@llvm-project//clang:tooling_core",
-    ],
-)
-
-cc_library(
-    name = "matcher_test_base",
-    testonly = 1,
-    hdrs = ["matcher_test_base.h"],
-    deps = [
-        ":matcher",
-        "@googletest//:gtest",
-        "@llvm-project//clang:ast_matchers",
-        "@llvm-project//clang:tooling",
-        "@llvm-project//clang:tooling_core",
-    ],
-)
-
-# Individual matchers
-
-cc_library(
-    name = "fn_inserter",
-    srcs = ["fn_inserter.cpp"],
-    hdrs = ["fn_inserter.h"],
-    deps = [
-        ":matcher",
-        "@llvm-project//clang:ast_matchers",
-    ],
-)
-
-cc_test(
-    name = "fn_inserter_test",
-    size = "small",
-    srcs = ["fn_inserter_test.cpp"],
-    deps = [
-        ":fn_inserter",
-        ":matcher_test_base",
-        "//testing/base:gtest_main",
-        "@googletest//:gtest",
-        "@llvm-project//clang:tooling",
-    ],
-)
-
-cc_library(
-    name = "for_range",
-    srcs = ["for_range.cpp"],
-    hdrs = ["for_range.h"],
-    deps = [
-        ":matcher",
-        "@llvm-project//clang:ast_matchers",
-    ],
-)
-
-cc_test(
-    name = "for_range_test",
-    size = "small",
-    srcs = ["for_range_test.cpp"],
-    deps = [
-        ":for_range",
-        ":matcher_test_base",
-        "//testing/base:gtest_main",
-        "@googletest//:gtest",
-        "@llvm-project//clang:tooling",
-    ],
-)
-
-cc_library(
-    name = "var_decl",
-    srcs = ["var_decl.cpp"],
-    hdrs = ["var_decl.h"],
-    deps = [
-        ":matcher",
-        "@llvm-project//clang:ast_matchers",
-        "@llvm-project//clang:type_nodes_gen",
-        "@llvm-project//llvm:Support",
-    ],
-)
-
-cc_test(
-    name = "var_decl_test",
-    size = "small",
-    srcs = ["var_decl_test.cpp"],
-    deps = [
-        ":matcher_test_base",
-        ":var_decl",
-        "//testing/base:gtest_main",
-        "@googletest//:gtest",
-        "@llvm-project//clang:tooling",
-    ],
-)

+ 0 - 50
migrate_cpp/cpp_refactoring/fn_inserter.cpp

@@ -1,50 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/fn_inserter.h"
-
-#include "clang/ASTMatchers/ASTMatchers.h"
-
-// NOLINTNEXTLINE(readability-identifier-naming)
-namespace cam = ::clang::ast_matchers;
-
-namespace Carbon {
-
-static constexpr char Label[] = "FnInserter";
-
-void FnInserter::Run() {
-  const auto& decl = GetNodeAsOrDie<clang::FunctionDecl>(Label);
-
-  // For names like "Class::Method", replace up to "Class" not "Method".
-  clang::NestedNameSpecifierLoc qual_loc = decl.getQualifierLoc();
-  clang::SourceLocation name_begin_loc =
-      qual_loc.hasQualifier() ? qual_loc.getBeginLoc() : decl.getLocation();
-  auto range =
-      clang::CharSourceRange::getCharRange(decl.getBeginLoc(), name_begin_loc);
-
-  // In order to handle keywords like "virtual" in "virtual auto Foo() -> ...",
-  // scan the replaced text and only drop auto/void entries.
-  llvm::SmallVector<llvm::StringRef> split;
-  GetSourceText(range).split(split, ' ', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-  std::string new_text = "fn ";
-  for (llvm::StringRef t : split) {
-    if (t != "auto" && t != "void") {
-      new_text += t.str() + " ";
-    }
-  }
-  AddReplacement(range, new_text);
-}
-
-void FnInserterFactory::AddMatcher(cam::MatchFinder* finder,
-                                   cam::MatchFinder::MatchCallback* callback) {
-  finder->addMatcher(
-      cam::functionDecl(cam::anyOf(cam::hasTrailingReturn(),
-                                   cam::returns(cam::asString("void"))),
-                        cam::unless(cam::anyOf(cam::cxxConstructorDecl(),
-                                               cam::cxxDestructorDecl())))
-          .bind(Label),
-      callback);
-}
-
-}  // namespace Carbon

+ 0 - 28
migrate_cpp/cpp_refactoring/fn_inserter.h

@@ -1,28 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_FN_INSERTER_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_FN_INSERTER_H_
-
-#include "migrate_cpp/cpp_refactoring/matcher.h"
-
-namespace Carbon {
-
-// Inserts `fn` for functions and methods.
-class FnInserter : public Matcher {
- public:
-  using Matcher::Matcher;
-  void Run() override;
-};
-
-class FnInserterFactory : public MatcherFactoryBase<FnInserter> {
- public:
-  void AddMatcher(
-      clang::ast_matchers::MatchFinder* finder,
-      clang::ast_matchers::MatchFinder::MatchCallback* callback) override;
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_FN_INSERTER_H_

+ 0 - 93
migrate_cpp/cpp_refactoring/fn_inserter_test.cpp

@@ -1,93 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/fn_inserter.h"
-
-#include "migrate_cpp/cpp_refactoring/matcher_test_base.h"
-
-namespace Carbon::Testing {
-namespace {
-
-class FnInserterTest : public MatcherTestBase<FnInserterFactory> {};
-
-TEST_F(FnInserterTest, TrailingReturn) {
-  constexpr char Before[] = "auto A() -> int;";
-  constexpr char After[] = "fn A() -> int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(FnInserterTest, Inline) {
-  constexpr char Before[] = "inline auto A() -> int;";
-  constexpr char After[] = "fn inline A() -> int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(FnInserterTest, Void) {
-  constexpr char Before[] = "void A();";
-  constexpr char After[] = "fn A();";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(FnInserterTest, Methods) {
-  constexpr char Before[] = R"cpp(
-    class Shape {
-     public:
-      virtual void Draw() = 0;
-      virtual auto NumSides() -> int = 0;
-    };
-
-    class Circle : public Shape {
-     public:
-      void Draw() override;
-      auto NumSides() -> int override;
-      auto Radius() -> double { return radius_; }
-
-     private:
-      double radius_;
-    };
-
-    void Shape::Draw() {}
-  )cpp";
-  constexpr char After[] = R"(
-    class Shape {
-     public:
-      fn virtual Draw() = 0;
-      fn virtual NumSides() -> int = 0;
-    };
-
-    class Circle : public Shape {
-     public:
-      fn Draw() override;
-      fn NumSides() -> int override;
-      fn Radius() -> double { return radius_; }
-
-     private:
-      double radius_;
-    };
-
-    fn Shape::Draw() {}
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(FnInserterTest, ConstructorDestructor) {
-  constexpr char Before[] = R"cpp(
-    class Shape {
-     public:
-      Shape() {}
-      ~Shape() {}
-    };
-  )cpp";
-  ExpectReplacement(Before, Before);
-}
-
-TEST_F(FnInserterTest, LegacyReturn) {
-  // Code should be migrated to trailing returns by clang-tidy, so this is okay
-  // to miss.
-  constexpr char Before[] = "int A();";
-  ExpectReplacement(Before, Before);
-}
-
-}  // namespace
-}  // namespace Carbon::Testing

+ 0 - 30
migrate_cpp/cpp_refactoring/for_range.cpp

@@ -1,30 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/for_range.h"
-
-#include "clang/ASTMatchers/ASTMatchers.h"
-
-// NOLINTNEXTLINE(readability-identifier-naming)
-namespace cam = ::clang::ast_matchers;
-
-namespace Carbon {
-
-static constexpr char Label[] = "ForRange";
-
-void ForRange::Run() {
-  const auto& stmt = GetNodeAsOrDie<clang::CXXForRangeStmt>(Label);
-
-  // Wrap `in` with spaces so that `for (auto i:items)` has valid results.
-  AddReplacement(clang::CharSourceRange::getTokenRange(stmt.getColonLoc(),
-                                                       stmt.getColonLoc()),
-                 " in ");
-}
-
-void ForRangeFactory::AddMatcher(cam::MatchFinder* finder,
-                                 cam::MatchFinder::MatchCallback* callback) {
-  finder->addMatcher(cam::cxxForRangeStmt().bind(Label), callback);
-}
-
-}  // namespace Carbon

+ 0 - 31
migrate_cpp/cpp_refactoring/for_range.h

@@ -1,31 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_FOR_RANGE_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_FOR_RANGE_H_
-
-#include "migrate_cpp/cpp_refactoring/matcher.h"
-
-namespace Carbon {
-
-// Updates variable declarations for `var name: type`.
-class ForRange : public Matcher {
- public:
-  using Matcher::Matcher;
-  void Run() override;
-
- private:
-  auto GetTypeStr(const clang::VarDecl& decl) -> std::string;
-};
-
-class ForRangeFactory : public MatcherFactoryBase<ForRange> {
- public:
-  void AddMatcher(
-      clang::ast_matchers::MatchFinder* finder,
-      clang::ast_matchers::MatchFinder::MatchCallback* callback) override;
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_FOR_RANGE_H_

+ 0 - 52
migrate_cpp/cpp_refactoring/for_range_test.cpp

@@ -1,52 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/for_range.h"
-
-#include "migrate_cpp/cpp_refactoring/matcher_test_base.h"
-
-namespace Carbon::Testing {
-namespace {
-
-class ForRangeTest : public MatcherTestBase<ForRangeFactory> {};
-
-TEST_F(ForRangeTest, Basic) {
-  constexpr char Before[] = R"cpp(
-    void Foo() {
-      int items[] = {1};
-      for (int i : items) {
-      }
-    }
-  )cpp";
-  constexpr char After[] = R"(
-    void Foo() {
-      int items[] = {1};
-      for (int i  in  items) {
-      }
-    }
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(ForRangeTest, NoSpace) {
-  // Do not mark `cpp` so that clang-format won't "fix" the `:` spacing.
-  constexpr char Before[] = R"(
-    void Foo() {
-      int items[] = {1};
-      for (int i:items) {
-      }
-    }
-  )";
-  constexpr char After[] = R"(
-    void Foo() {
-      int items[] = {1};
-      for (int i in items) {
-      }
-    }
-  )";
-  ExpectReplacement(Before, After);
-}
-
-}  // namespace
-}  // namespace Carbon::Testing

+ 0 - 44
migrate_cpp/cpp_refactoring/main.cpp

@@ -1,44 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "clang/Tooling/CommonOptionsParser.h"
-#include "clang/Tooling/Refactoring.h"
-#include "migrate_cpp/cpp_refactoring/fn_inserter.h"
-#include "migrate_cpp/cpp_refactoring/for_range.h"
-#include "migrate_cpp/cpp_refactoring/matcher_manager.h"
-#include "migrate_cpp/cpp_refactoring/var_decl.h"
-
-using clang::tooling::RefactoringTool;
-
-// Initialize the files in replacements. Matcher will restrict replacements to
-// initialized files.
-static void InitReplacements(RefactoringTool* tool) {
-  clang::FileManager& files = tool->getFiles();
-  Carbon::Matcher::ReplacementMap& repl = tool->getReplacements();
-  for (const std::string& path : tool->getSourcePaths()) {
-    llvm::Expected<clang::FileEntryRef> file = files.getFileRef(path);
-    if (!file) {
-      llvm::report_fatal_error(llvm::Twine("Error accessing `") + path +
-                               "`: " + llvm::toString(file.takeError()) + "\n");
-    }
-    repl.insert({files.getCanonicalName(*file).str(), {}});
-  }
-}
-
-auto main(int argc, const char** argv) -> int {
-  llvm::cl::OptionCategory category("C++ refactoring options");
-  auto parser =
-      clang::tooling::CommonOptionsParser::create(argc, argv, category);
-  RefactoringTool tool(parser->getCompilations(), parser->getSourcePathList());
-  InitReplacements(&tool);
-
-  // Set up AST matcher callbacks.
-  Carbon::MatcherManager matchers(&tool.getReplacements());
-  matchers.Register(std::make_unique<Carbon::FnInserterFactory>());
-  matchers.Register(std::make_unique<Carbon::ForRangeFactory>());
-  matchers.Register(std::make_unique<Carbon::VarDeclFactory>());
-
-  return tool.runAndSave(
-      clang::tooling::newFrontendActionFactory(matchers.GetFinder()).get());
-}

+ 0 - 46
migrate_cpp/cpp_refactoring/matcher.cpp

@@ -1,46 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/matcher.h"
-
-#include "clang/Basic/SourceManager.h"
-
-namespace Carbon {
-
-void Matcher::AddReplacement(clang::CharSourceRange range,
-                             llvm::StringRef replacement_text) {
-  if (!range.isValid()) {
-    // Invalid range.
-    return;
-  }
-  const auto& source_manager = GetSourceManager();
-  if (source_manager.getDecomposedLoc(range.getBegin()).first !=
-      source_manager.getDecomposedLoc(range.getEnd()).first) {
-    // Range spans macro expansions.
-    return;
-  }
-  if (source_manager.getFileID(range.getBegin()) !=
-      source_manager.getFileID(range.getEnd())) {
-    // Range spans files.
-    return;
-  }
-
-  clang::tooling::Replacement rep(source_manager,
-                                  source_manager.getExpansionRange(range),
-                                  replacement_text);
-  auto entry = replacements->find(std::string(rep.getFilePath()));
-  if (entry == replacements->end()) {
-    // The replacement was in a file which isn't being updated, such as a system
-    // header.
-    return;
-  }
-
-  llvm::Error err = entry->second.add(rep);
-  if (err) {
-    llvm::errs() << "Error with replacement `" << rep.toString()
-                 << "`: " << llvm::toString(std::move(err)) << "\n";
-  }
-}
-
-}  // namespace Carbon

+ 0 - 95
migrate_cpp/cpp_refactoring/matcher.h

@@ -1,95 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_H_
-
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/Core/Replacement.h"
-
-namespace Carbon {
-
-// This is an abstract class with helpers to make it easier to write matchers.
-// Note a MatcherFactory (below) is also typically required.
-class Matcher {
- public:
-  using ReplacementMap = std::map<std::string, clang::tooling::Replacements>;
-
-  Matcher(const clang::ast_matchers::MatchFinder::MatchResult* in_match_result,
-          ReplacementMap* in_replacements)
-      : match_result(in_match_result), replacements(in_replacements) {}
-  virtual ~Matcher() = default;
-
-  // Performs main execution of the matcher when a result is found.
-  virtual void Run() = 0;
-
- protected:
-  // Replaces the given range with the specified text.
-  void AddReplacement(clang::CharSourceRange range,
-                      llvm::StringRef replacement_text);
-
-  // Returns a matched node by ID, exiting if not present.
-  template <typename NodeType>
-  auto GetNodeAsOrDie(llvm::StringRef id) -> const NodeType& {
-    auto* node = match_result->Nodes.getNodeAs<NodeType>(id);
-    if (!node) {
-      llvm::report_fatal_error(std::string("getNodeAs failed for ") + id);
-    }
-    return *node;
-  }
-
-  // Returns the language options.
-  auto GetLangOpts() -> const clang::LangOptions& {
-    return match_result->Context->getLangOpts();
-  }
-
-  // Returns the full source manager.
-  auto GetSourceManager() -> const clang::SourceManager& {
-    return *match_result->SourceManager;
-  }
-
-  // Returns the source text for a given range.
-  auto GetSourceText(clang::CharSourceRange range) -> llvm::StringRef {
-    return clang::Lexer::getSourceText(range, GetSourceManager(),
-                                       GetLangOpts());
-  }
-
- private:
-  const clang::ast_matchers::MatchFinder::MatchResult* const match_result;
-  ReplacementMap* const replacements;
-};
-
-// A factory used to instantiate per-MatchResult Matchers, to be registered with
-// the MatcherManager.
-class MatcherFactory {
- public:
-  virtual ~MatcherFactory() = default;
-
-  virtual auto CreateMatcher(
-      const clang::ast_matchers::MatchFinder::MatchResult* match_result,
-      Matcher::ReplacementMap* replacements) -> std::unique_ptr<Matcher> = 0;
-
-  // Adds the Matcher to the finder with the provided callback.
-  virtual void AddMatcher(
-      clang::ast_matchers::MatchFinder* finder,
-      clang::ast_matchers::MatchFinder::MatchCallback* callback) = 0;
-};
-
-// A convenience factory that implements CreateMatcher for Matchers that have a
-// standard constructor.
-template <typename MatcherType>
-class MatcherFactoryBase : public MatcherFactory {
- public:
-  auto CreateMatcher(
-      const clang::ast_matchers::MatchFinder::MatchResult* match_result,
-      Matcher::ReplacementMap* replacements)
-      -> std::unique_ptr<Matcher> override {
-    return std::make_unique<MatcherType>(match_result, replacements);
-  }
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_H_

+ 0 - 58
migrate_cpp/cpp_refactoring/matcher_manager.h

@@ -1,58 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_MANAGER_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_MANAGER_H_
-
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Tooling/Core/Replacement.h"
-#include "migrate_cpp/cpp_refactoring/matcher.h"
-
-namespace Carbon {
-
-// Manages registration of AST matchers.
-class MatcherManager {
- public:
-  explicit MatcherManager(Matcher::ReplacementMap* in_replacements)
-      : replacements(in_replacements) {}
-
-  // Registers Matcher implementations.
-  void Register(std::unique_ptr<MatcherFactory> factory) {
-    matchers.push_back(std::make_unique<MatchCallbackWrapper>(
-        &finder, std::move(factory), replacements));
-  }
-
-  auto GetFinder() -> clang::ast_matchers::MatchFinder* { return &finder; }
-
- private:
-  // Adapts Matcher for use with MatchCallback.
-  class MatchCallbackWrapper
-      : public clang::ast_matchers::MatchFinder::MatchCallback {
-   public:
-    explicit MatchCallbackWrapper(clang::ast_matchers::MatchFinder* finder,
-                                  std::unique_ptr<MatcherFactory> in_factory,
-                                  Matcher::ReplacementMap* in_replacements)
-        : factory(std::move(in_factory)), replacements(in_replacements) {
-      factory->AddMatcher(finder, this);
-    }
-
-    void run(const clang::ast_matchers::MatchFinder::MatchResult& match_result)
-        override {
-      factory->CreateMatcher(&match_result, replacements)->Run();
-    }
-
-   private:
-    std::unique_ptr<MatcherFactory> factory;
-    Matcher::ReplacementMap* const replacements;
-  };
-
-  Matcher::ReplacementMap* const replacements;
-  clang::ast_matchers::MatchFinder finder;
-  std::vector<std::unique_ptr<MatcherFactory>> factories;
-  std::vector<std::unique_ptr<MatchCallbackWrapper>> matchers;
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_MANAGER_H_

+ 0 - 67
migrate_cpp/cpp_refactoring/matcher_test_base.h

@@ -1,67 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_TEST_BASE_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_TEST_BASE_H_
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Tooling/Core/Replacement.h"
-#include "clang/Tooling/Tooling.h"
-#include "migrate_cpp/cpp_refactoring/matcher_manager.h"
-
-namespace Carbon::Testing {
-
-// Matcher test framework.
-template <typename MatcherFactoryType>
-class MatcherTestBase : public ::testing::Test {
- protected:
-  MatcherTestBase() : matchers_(&replacements_) {
-    matchers_.Register(std::make_unique<MatcherFactoryType>());
-  }
-
-  // Expects that the replacements produced by running the finder result in
-  // the specified code transformation.
-  void ExpectReplacement(llvm::StringRef before, llvm::StringRef after) {
-    auto factory =
-        clang::tooling::newFrontendActionFactory(matchers_.GetFinder());
-    constexpr char Filename[] = "test.cc";
-    replacements_.clear();
-    replacements_.insert({Filename, {}});
-    ASSERT_TRUE(clang::tooling::runToolOnCodeWithArgs(
-        factory->create(), before, {}, Filename, "clang-tool",
-        std::make_shared<clang::PCHContainerOperations>(),
-        clang::tooling::FileContentMappings()));
-    EXPECT_THAT(replacements_, testing::ElementsAre(testing::Key(Filename)));
-    llvm::Expected<std::string> actual =
-        clang::tooling::applyAllReplacements(before, replacements_[Filename]);
-
-    // Make a specific note if the matcher didn't make any changes.
-    std::string unchanged;
-    if (before == *actual) {
-      unchanged = "NOTE: Actual matches original text, no changes made.";
-    }
-
-    if (after.find('\n') == std::string::npos) {
-      EXPECT_THAT(*actual, testing::Eq(after.str())) << unchanged;
-    } else {
-      // Split lines to get gmock to get an easier-to-read error.
-      llvm::SmallVector<llvm::StringRef, 0> actual_lines;
-      llvm::SplitString(*actual, actual_lines, "\n");
-      llvm::SmallVector<llvm::StringRef, 0> after_lines;
-      llvm::SplitString(after, after_lines, "\n");
-      EXPECT_THAT(actual_lines, testing::ContainerEq(after_lines)) << unchanged;
-    }
-  }
-
- private:
-  Matcher::ReplacementMap replacements_;
-  MatcherManager matchers_;
-};
-
-}  // namespace Carbon::Testing
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_MATCHER_TEST_BASE_H_

+ 0 - 144
migrate_cpp/cpp_refactoring/var_decl.cpp

@@ -1,144 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/var_decl.h"
-
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "llvm/Support/FormatVariadic.h"
-
-// NOLINTNEXTLINE(readability-identifier-naming)
-namespace cam = ::clang::ast_matchers;
-
-namespace Carbon {
-
-static constexpr char Label[] = "VarDecl";
-
-// Helper function for printing TypeLocClass. Useful for debugging.
-LLVM_ATTRIBUTE_UNUSED
-static auto TypeLocClassToString(clang::TypeLoc::TypeLocClass c)
-    -> std::string {
-  switch (c) {
-    // Mirrors the definition in clang/AST/TypeLoc.h in order to print names.
-#define ABSTRACT_TYPE(Class, Base)
-#define TYPE(Class, Base)     \
-  case clang::TypeLoc::Class: \
-    return #Class;
-#include "clang/AST/TypeNodes.inc"
-    case clang::TypeLoc::Qualified:
-      return "Qualified";
-  }
-}
-
-// Returns a string for the type.
-auto VarDecl::GetTypeStr(const clang::VarDecl& decl) -> std::string {
-  // Built a vector of class information, because we'll be traversing reverse
-  // order to construct the final type.
-  auto type_loc = decl.getTypeSourceInfo()->getTypeLoc();
-  std::vector<std::pair<clang::TypeLoc::TypeLocClass, std::string>> segments;
-  while (!type_loc.isNull()) {
-    auto qualifiers = type_loc.getType().getLocalQualifiers();
-    std::string qual_str;
-    if (!qualifiers.empty()) {
-      qual_str = qualifiers.getAsString();
-    }
-    auto range =
-        clang::CharSourceRange::getTokenRange(type_loc.getLocalSourceRange());
-    std::string range_str = GetSourceText(range).str();
-
-    // Make a list of segments with their TypeLocClass for reconstruction of the
-    // string. Locally, we will have a qualifier (such as `const`) and a type
-    // string (such as `int`) which is also used.
-    auto type_loc_class = type_loc.getTypeLocClass();
-    if (qual_str.empty()) {
-      segments.push_back({type_loc_class, range_str});
-    } else if (range_str.empty()) {
-      segments.push_back({type_loc_class, qual_str});
-    } else {
-      segments.push_back(
-          {type_loc_class, llvm::formatv("{0} {1}", qual_str, range_str)});
-    }
-
-    type_loc = type_loc.getNextTypeLoc();
-  }
-
-  // Construct the final type based on the class of each step. This reverses to
-  // start from the "inside" of the type and go "out" when constructing
-  // type_str.
-  std::string type_str;
-  auto prev_class = clang::TypeLoc::Auto;  // Placeholder class, used in loop.
-  for (const auto& [type_loc_class, text] : llvm::reverse(segments)) {
-    switch (type_loc_class) {
-      case clang::TypeLoc::Elaborated:
-        type_str.insert(0, text);
-        break;
-      case clang::TypeLoc::Qualified:
-        if (prev_class == clang::TypeLoc::Pointer) {
-          type_str += " " + text;
-        } else {
-          if (!type_str.empty()) {
-            type_str.insert(0, " ");
-          }
-          type_str.insert(0, text);
-        }
-        break;
-      default:
-        type_str += text;
-        break;
-    }
-    prev_class = type_loc_class;
-  }
-  return type_str;
-}
-
-void VarDecl::Run() {
-  const auto& decl = GetNodeAsOrDie<clang::VarDecl>(Label);
-  if (decl.getTypeSourceInfo() == nullptr) {
-    // TODO: Need to understand what's happening in this case. Not sure if we
-    // need to address it.
-    return;
-  }
-
-  std::string after;
-  if (decl.getType().isConstQualified()) {
-    after = "let ";
-  } else if (!llvm::isa<clang::ParmVarDecl>(&decl)) {
-    // Start the replacement with "var" unless it's a parameter.
-    after = "var ";
-  }
-  // Add "identifier: type" to the replacement.
-  after += decl.getNameAsString() + ": " + GetTypeStr(decl);
-
-  // This decides the range to replace. Normally the entire decl is replaced,
-  // but for code like `int i, j` we need to detect the comma between the
-  // declared names. That case currently results in `var i: int, var j: int`.
-  // If there's a comma, this range will be non-empty.
-  auto type_loc = decl.getTypeSourceInfo()->getTypeLoc();
-  clang::SourceLocation after_type_loc = clang::Lexer::getLocForEndOfToken(
-      type_loc.getEndLoc(), 0, GetSourceManager(), GetLangOpts());
-  llvm::StringRef comma_source_text = GetSourceText(
-      clang::CharSourceRange::getCharRange(after_type_loc, decl.getLocation()));
-  clang::SourceLocation replace_start = !comma_source_text.trim().empty()
-                                            ? decl.getLocation()
-                                            : decl.getBeginLoc();
-
-  // Figure out where the replacement ends and initialization begins. For
-  // example, `int i` the end is the identifier, `int i[4]` the end is the `[4]`
-  // type qualifier.
-  clang::SourceLocation identifier_end = clang::Lexer::getLocForEndOfToken(
-      decl.getLocation(), 0, GetSourceManager(), GetLangOpts());
-  clang::SourceLocation replace_end = std::max(identifier_end, after_type_loc);
-
-  AddReplacement(
-      clang::CharSourceRange::getCharRange(replace_start, replace_end), after);
-}
-
-void VarDeclFactory::AddMatcher(cam::MatchFinder* finder,
-                                cam::MatchFinder::MatchCallback* callback) {
-  finder->addMatcher(cam::varDecl(cam::unless(cam::hasParent(cam::declStmt(
-                                      cam::hasParent(cam::cxxForRangeStmt())))))
-                         .bind(Label),
-                     callback);
-}
-
-}  // namespace Carbon

+ 0 - 31
migrate_cpp/cpp_refactoring/var_decl.h

@@ -1,31 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_CPP_REFACTORING_VAR_DECL_H_
-#define CARBON_MIGRATE_CPP_CPP_REFACTORING_VAR_DECL_H_
-
-#include "migrate_cpp/cpp_refactoring/matcher.h"
-
-namespace Carbon {
-
-// Updates variable declarations for `var name: type`.
-class VarDecl : public Matcher {
- public:
-  using Matcher::Matcher;
-  void Run() override;
-
- private:
-  auto GetTypeStr(const clang::VarDecl& decl) -> std::string;
-};
-
-class VarDeclFactory : public MatcherFactoryBase<VarDecl> {
- public:
-  void AddMatcher(
-      clang::ast_matchers::MatchFinder* finder,
-      clang::ast_matchers::MatchFinder::MatchCallback* callback) override;
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_CPP_REFACTORING_VAR_DECL_H_

+ 0 - 257
migrate_cpp/cpp_refactoring/var_decl_test.cpp

@@ -1,257 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/cpp_refactoring/var_decl.h"
-
-#include "migrate_cpp/cpp_refactoring/matcher_test_base.h"
-
-namespace Carbon::Testing {
-namespace {
-
-class VarDeclTest : public MatcherTestBase<VarDeclFactory> {};
-
-TEST_F(VarDeclTest, Declaration) {
-  constexpr char Before[] = "int i;";
-  constexpr char After[] = "var i: int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationArray) {
-  constexpr char Before[] = "int i[4];";
-  constexpr char After[] = "var i: int[4];";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationConstArray) {
-  constexpr char Before[] = "const int i[] = {0, 1};";
-  constexpr char After[] = "let i: const int[] = {0, 1};";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationConstPointer) {
-  // TODO: Fix j replacement location.
-  constexpr char Before[] = R"cpp(
-    int i = 0;
-    int* const j = &i;
-    const int* k = &i;
-  )cpp";
-  constexpr char After[] = R"(
-    var i: int = 0;
-    int* const let j: int* const = &i;
-    var k: const int* = &i;
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationComma) {
-  // TODO: Maybe replace the comma with a `;`.
-  constexpr char Before[] = "int i, j;";
-  constexpr char After[] = "var i: int, var j: int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationCommaAssignment) {
-  // TODO: Maybe replace the comma with a `;`.
-  constexpr char Before[] = "int i = 0, j = 0;";
-  constexpr char After[] = "var i: int = 0, var j: int = 0;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationCommaArray) {
-  // TODO: Maybe replace the comma with a `;`.
-  // TODO: Need to handle j's array.
-  constexpr char Before[] = "int i[4], j[4];";
-  constexpr char After[] = "var i: int[4], j[4];";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationCommaArrayAssignment) {
-  // TODO: Maybe replace the comma with a `;`.
-  // TODO: Need to handle j's array.
-  constexpr char Before[] = "int i[] = {0}, j[] = {1};";
-  constexpr char After[] = "var i: int[] = {0}, j[] = {1};";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationCommaPointers) {
-  // TODO: Maybe replace the comma with a `;`.
-  // TODO: Need to handle j's pointer.
-  // constexpr char After[] = "var i: int *, var j: int *;";
-  constexpr char Before[] = "int *i, *j;";
-  constexpr char After[] = "var i: int*, *j;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, DeclarationCommaPointersAssignment) {
-  // TODO: Maybe replace the comma with a `;`.
-  // TODO: Need to handle j's pointer.
-  // constexpr char After[] = "var i: int *, var j: int *;";
-  constexpr char Before[] = "int *i = nullptr, *j = i;";
-  constexpr char After[] = "var i: int* = nullptr, *j = i;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Assignment) {
-  constexpr char Before[] = "int i = 0;";
-  constexpr char After[] = "var i: int = 0;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Auto) {
-  constexpr char Before[] = "auto i = 0;";
-  constexpr char After[] = "var i: auto = 0;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, AutoRef) {
-  constexpr char Before[] = R"cpp(
-    auto i = 0;
-    const auto& j = i;
-  )cpp";
-  constexpr char After[] = R"(
-    var i: auto = 0;
-    var j: const auto& = i;
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Const) {
-  constexpr char Before[] = "const int i = 0;";
-  constexpr char After[] = "let i: const int = 0;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, ConstPointer) {
-  constexpr char Before[] = "const int* i;";
-  constexpr char After[] = "var i: const int*;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Namespace) {
-  constexpr char Before[] = R"cpp(
-    namespace Foo {
-    typedef int Bar;
-    }
-    Foo::Bar x;
-  )cpp";
-  constexpr char After[] = R"(
-    namespace Foo {
-    typedef int Bar;
-    }
-    var x: Foo::Bar;
-  )";
-  ExpectReplacement(Before, After);
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Params) {
-  constexpr char Before[] = "auto Foo(int i) -> int;";
-  constexpr char After[] = "auto Foo(i: int) -> int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, ParamsDefault) {
-  constexpr char Before[] = "auto Foo(int i = 0) -> int;";
-  constexpr char After[] = "auto Foo(i: int = 0) -> int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, ParamsConst) {
-  constexpr char Before[] = "auto Foo(const int i) -> int;";
-  constexpr char After[] = "auto Foo(let i: const int) -> int;";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, ParamStruct) {
-  // This is to ensure the 'struct' keyword doesn't get added to the qualified
-  // type.
-  constexpr char Before[] = R"cpp(
-    struct Circle {};
-    auto Draw(int times, const Circle& circle) -> bool;
-  )cpp";
-  constexpr char After[] = R"(
-    struct Circle {};
-    auto Draw(times: int, circle: const Circle&) -> bool;
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Member) {
-  // TODO: Handle member variables.
-  constexpr char Before[] = R"cpp(
-    struct Circle {
-      Circle() : x(0), y(0), radius(1) {}
-
-      int x;
-      int y;
-      int radius;
-    };
-  )cpp";
-  ExpectReplacement(Before, Before);
-}
-
-TEST_F(VarDeclTest, Constructor) {
-  constexpr char Before[] = R"cpp(
-    struct Index {
-      Index(int i) : i(i) {}
-
-      int i;
-    };
-    Index x(0);
-  )cpp";
-  constexpr char After[] = R"(
-    struct Index {
-      Index(i: int) : i(i) {}
-
-      int i;
-    };
-    var x: Index(0);
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, RangeFor) {
-  constexpr char Before[] = R"cpp(
-    void Foo() {
-      int items[] = {1};
-      for (int i : items) {
-        int j;
-      }
-    }
-  )cpp";
-  constexpr char After[] = R"(
-    void Foo() {
-      var items: int[] = {1};
-      for (int i : items) {
-        var j: int;
-      }
-    }
-  )";
-  ExpectReplacement(Before, After);
-}
-
-TEST_F(VarDeclTest, Template) {
-  constexpr char Before[] = R"cpp(
-    template <typename T>
-    struct R {};
-
-    template <typename T>
-    struct S {};
-
-    R<S<int>> x;
-  )cpp";
-  constexpr char After[] = R"(
-    template <typename T>
-    struct R {};
-
-    template <typename T>
-    struct S {};
-
-    var x: R<S<int>>;
-  )";
-  ExpectReplacement(Before, After);
-}
-
-}  // namespace
-}  // namespace Carbon::Testing

+ 0 - 118
migrate_cpp/migrate_cpp.py

@@ -1,118 +0,0 @@
-"""Migrates C++ code to Carbon."""
-
-__copyright__ = """
-Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-Exceptions. See /LICENSE for license information.
-SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-"""
-
-import argparse
-import glob
-import os
-import subprocess
-import sys
-from typing import Optional
-
-_CPP_REFACTORING = "./cpp_refactoring/cpp_refactoring"
-_H_EXTS = {".h", ".hpp"}
-_CPP_EXTS = {".c", ".cc", ".cpp", ".cxx"}
-
-
-class _Workflow:
-    _parsed_args: argparse.Namespace
-    _data_dir: str
-    _cpp_files: Optional[list[str]]
-
-    def __init__(self) -> None:
-        """Parses command-line arguments and flags."""
-        parser = argparse.ArgumentParser(description=__doc__)
-        parser.add_argument(
-            "dir",
-            type=str,
-            help="A directory containing C++ files to migrate to Carbon.",
-        )
-        parsed_args = parser.parse_args()
-        self._parsed_args = parsed_args
-
-        self._data_dir = os.path.dirname(sys.argv[0])
-
-        # Validate arguments.
-        if not os.path.isdir(parsed_args.dir):
-            sys.exit("%r must point to a directory." % parsed_args.dir)
-
-    def run(self) -> None:
-        """Runs the migration workflow."""
-        try:
-            self._gather_files()
-            self._clang_tidy()
-            self._cpp_refactoring()
-            self._rename_files()
-            self._print_header("Done!")
-        except subprocess.CalledProcessError as e:
-            # Discard the stack for subprocess errors.
-            sys.exit(str(e))
-
-    def _data_file(self, relative_path: str) -> str:
-        """Returns the path to a data file."""
-        return os.path.join(self._data_dir, relative_path)
-
-    @staticmethod
-    def _print_header(header: str) -> None:
-        print("*" * 79)
-        print("* %-75s *" % header)
-        print("*" * 79)
-
-    def _gather_files(self) -> None:
-        """Returns the list of C++ files to convert."""
-        self._print_header("Gathering C++ files...")
-        all_files = glob.glob(
-            os.path.join(self._parsed_args.dir, "**/*.*"), recursive=True
-        )
-        exts = _CPP_EXTS.union(_H_EXTS)
-        cpp_files = [f for f in all_files if os.path.splitext(f)[1] in exts]
-        if not cpp_files:
-            sys.exit(
-                "%r doesn't contain any C++ files to convert."
-                % self._parsed_args.dir
-            )
-        self._cpp_files = sorted(cpp_files)
-        print("%d files found." % len(self._cpp_files))
-
-    def _clang_tidy(self) -> None:
-        """Runs clang-tidy to fix C++ files in a directory."""
-        self._print_header("Running clang-tidy...")
-        with open(self._data_file("clang_tidy.yaml")) as f:
-            config = f.read()
-        subprocess.run(
-            ["run-clang-tidy.py", "-fix", "-config", config],
-            check=True,
-        )
-
-    def _cpp_refactoring(self) -> None:
-        """Runs cpp_refactoring to migrate C++ files towards Carbon syntax."""
-        self._print_header("Running cpp_refactoring...")
-        cpp_refactoring = self._data_file(_CPP_REFACTORING)
-        assert self._cpp_files is not None
-        subprocess.run([cpp_refactoring] + self._cpp_files, check=True)
-
-    def _rename_files(self) -> None:
-        """Renames C++ files to the destination Carbon filenames."""
-        api_renames = 0
-        impl_renames = 0
-        assert self._cpp_files is not None
-        for f in self._cpp_files:
-            parts = os.path.splitext(f)
-            if parts[1] in _H_EXTS:
-                os.rename(f, parts[0] + ".carbon")
-                api_renames += 1
-            else:
-                os.rename(f, parts[0] + ".impl.carbon")
-                impl_renames += 1
-        print(
-            "Renaming resulted in %d API files and %d impl files."
-            % (api_renames, impl_renames)
-        )
-
-
-if __name__ == "__main__":
-    _Workflow().run()

+ 0 - 89
migrate_cpp/output_segment.h

@@ -1,89 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_OUTPUT_SEGMENT_H_
-#define CARBON_MIGRATE_CPP_OUTPUT_SEGMENT_H_
-
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <variant>
-
-#include "clang/AST/ASTTypeTraits.h"
-#include "common/check.h"
-
-namespace Carbon {
-
-namespace Internal {
-// Checks that the type T is an acceptable node type from which an
-// OutputSegment can be constructed. We intentionally do not want to support
-// `clang::Type` because we support traversing through `clang::TypeLoc`
-// instead. However, most other types we intend to support as they become
-// necessary.
-template <typename T>
-concept IsSupportedClangASTNodeType = std::convertible_to<T*, clang::Stmt*> ||
-                                      std::convertible_to<T*, clang::Decl*>;
-}  // namespace Internal
-
-// Represents a segment of the output string. `OutputSegment`s come in two
-// flavors: Text and Node. A text segment holds string text that should be used
-// to be added to the output. A node segment holds a node in Clang's AST and
-// indicates that the output associated to that node should be the output
-// segment that the `RewriteBuilder` (defined below) has attached to that AST
-// node.
-//
-// For example, the output for a binary operator node corresponding to the C++
-// code snippet `f() + 3 * 5`, would be the sequence of three output segments:
-//
-//                  {Node(lhs), Text(" + "), Node(rhs)}
-//
-// The left-hand side and right-hand side can then be queried recursively to
-// determine what their output should be.
-class OutputSegment {
- public:
-  // Creates a text-based `OutputSegment`.
-  explicit OutputSegment(std::string content) : content_(std::move(content)) {}
-  explicit OutputSegment(llvm::StringRef content) : content_(content.str()) {}
-  explicit OutputSegment(const char* content) : content_(content) {}
-
-  // Creates a node-based `OutputSegment` from `node`.
-  explicit OutputSegment(const clang::DynTypedNode& node) : content_(node) {}
-  template <typename T>
-    requires Internal::IsSupportedClangASTNodeType<T>
-  explicit OutputSegment(const T* node);
-
-  // Creates a TypeLoc-based `OutputSegment` from `type_loc`.
-  explicit OutputSegment(clang::TypeLoc type_loc)
-      : content_(PassThroughQualifiedTypeLoc(type_loc)) {}
-
- private:
-  friend struct OutputWriter;
-
-  template <typename T>
-  auto AssertNotNull(T* ptr) -> T& {
-    CARBON_CHECK(ptr != nullptr);
-    return *ptr;
-  }
-
-  // Traversals for TypeLocs have some sharp corners. In particular,
-  // QualifiedTypeLocs are silently passed through to their unqualified part.
-  // This means that when constructing output segments we also need to match
-  // this behavior.
-  static auto PassThroughQualifiedTypeLoc(clang::TypeLoc type_loc)
-      -> clang::TypeLoc {
-    auto qtl = type_loc.getAs<clang::QualifiedTypeLoc>();
-    return qtl.isNull() ? type_loc : qtl.getUnqualifiedLoc();
-  }
-
-  std::variant<std::string, clang::DynTypedNode, clang::TypeLoc> content_;
-};
-
-template <typename T>
-  requires Internal::IsSupportedClangASTNodeType<T>
-OutputSegment::OutputSegment(const T* node)
-    : content_(clang::DynTypedNode::create(AssertNotNull(node))) {}
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_OUTPUT_SEGMENT_H_

+ 0 - 378
migrate_cpp/rewriter.cpp

@@ -1,378 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/rewriter.h"
-
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/FormatVariadic.h"
-
-namespace Carbon {
-
-static constexpr const char CppPlaceholder[] = "__cpp__{ ... }";
-
-auto OutputWriter::Write(clang::SourceLocation loc,
-                         const OutputSegment& segment) const -> bool {
-  return std::visit(
-      [&](auto& content) {
-        using Type = std::decay_t<decltype(content)>;
-        auto [begin, end] = bounds;
-
-        if constexpr (std::is_same_v<Type, std::string>) {
-          auto begin_offset = source_manager.getDecomposedLoc(loc).second;
-          // Append the string replacement if the node being replaced falls
-          // within `bounds`.
-          if (begin <= begin_offset && begin_offset < end) {
-            output.append(content);
-          }
-        } else if constexpr (std::is_same_v<Type, clang::DynTypedNode> ||
-                             std::is_same_v<Type, clang::TypeLoc>) {
-          auto content_loc = content.getSourceRange().getBegin();
-          auto begin_offset =
-              source_manager.getDecomposedLoc(content_loc).second;
-          // If the node we're considering a replacement for is already beyond
-          // the region for which we want to make a replacement, exit early
-          // declaring that we have completed replacements (by returning false).
-          // Otherwise proceed. Note that we do not exit early or skip anything
-          // if the node comes before the relevant region. This is because many
-          // nodes in Clang's AST have a starting source location but a
-          // meaningless end location, and while the start of the segment may
-          // not be in the range, as we recurse, sub-segments may indeed end up
-          // being printed.
-          if (begin_offset >= end) {
-            return false;
-          }
-
-          if (auto iter = map.find(content); iter == map.end()) {
-            output.append(CppPlaceholder);
-          } else {
-            for (const auto& output_segment : iter->second) {
-              if (!Write(content.getSourceRange().getBegin(), output_segment)) {
-                return false;
-              }
-            }
-          }
-        } else {
-          static_assert(std::is_void_v<Type>,
-                        "Failed to handle a case in the `std::variant`.");
-        }
-        return true;
-      },
-      segment.content_);
-}
-
-auto MigrationConsumer::HandleTranslationUnit(clang::ASTContext& context)
-    -> void {
-  RewriteBuilder rewriter(context, segment_map_);
-  rewriter.TraverseAST(context);
-
-  auto translation_unit_node =
-      clang::DynTypedNode::create(*context.getTranslationUnitDecl());
-  auto iter = segment_map_.find(translation_unit_node);
-
-  if (iter == segment_map_.end()) {
-    result_.append(CppPlaceholder);
-  } else {
-    OutputWriter w{
-        .map = segment_map_,
-        .bounds = output_range_,
-        .source_manager = context.getSourceManager(),
-        .output = result_,
-    };
-
-    for (const auto& output_segment : iter->second) {
-      w.Write(translation_unit_node.getSourceRange().getBegin(),
-              output_segment);
-    }
-  }
-}
-
-auto RewriteBuilder::TextFor(clang::SourceLocation begin,
-                             clang::SourceLocation end) const
-    -> llvm::StringRef {
-  auto range = clang::CharSourceRange::getCharRange(begin, end);
-  return clang::Lexer::getSourceText(range, context_.getSourceManager(),
-                                     context_.getLangOpts());
-}
-
-auto RewriteBuilder::TextForTokenAt(clang::SourceLocation loc) const
-    -> llvm::StringRef {
-  auto& source_manager = context_.getSourceManager();
-  auto [file_id, offset] = source_manager.getDecomposedLoc(loc);
-  llvm::StringRef file = source_manager.getBufferData(file_id);
-  clang::Lexer lexer(source_manager.getLocForStartOfFile(file_id),
-                     context_.getLangOpts(), file.begin(), file.data() + offset,
-                     file.end());
-  clang::Token token;
-  lexer.LexFromRawLexer(token);
-  return TextFor(loc, loc.getLocWithOffset(token.getLength()));
-}
-
-// TODO: The output written in this member function needs to be
-// architecture-dependent. Moreover, even if the output is correct in the sense
-// that the types match and are interoperable between Carbon and C++, they may
-// not be semantically correct: If the C++ code specifies the type `long`, and
-// on the platform for which the migration is occurring `long` has 64-bits, we
-// may not want to use `i64` as the replacement: The C++ code may be intended to
-// operate in environments where `long` is only 32-bits wide. We need to develop
-// a strategy for determining builtin-type replacements that addresses these
-// issues.
-auto RewriteBuilder::VisitBuiltinTypeLoc(clang::BuiltinTypeLoc type_loc)
-    -> bool {
-  llvm::StringRef content;
-  switch (type_loc.getTypePtr()->getKind()) {
-    case clang::BuiltinType::Bool:
-      content = "bool";
-      break;
-    case clang::BuiltinType::Char_U:
-      content = "char";
-      break;
-    case clang::BuiltinType::UChar:
-      content = "u8";
-      break;
-    case clang::BuiltinType::UShort:
-      content = "u16";
-      break;
-    case clang::BuiltinType::UInt:
-      content = "u32";
-      break;
-    case clang::BuiltinType::ULong:
-      content = "u64";
-      break;
-    case clang::BuiltinType::ULongLong:
-      content = "u64";
-      break;
-    case clang::BuiltinType::UInt128:
-      content = "u128";
-      break;
-    case clang::BuiltinType::Char_S:
-      content = "char";
-      break;
-    case clang::BuiltinType::SChar:
-      content = "i8";
-      break;
-    case clang::BuiltinType::Short:
-      content = "i16";
-      break;
-    case clang::BuiltinType::Int:
-      content = "i32";
-      break;
-    case clang::BuiltinType::Long:
-      content = "i64";
-      break;
-    case clang::BuiltinType::LongLong:
-      content = "i64";
-      break;
-    case clang::BuiltinType::Int128:
-      content = "i128";
-      break;
-    case clang::BuiltinType::Float:
-      content = "f32";
-      break;
-    case clang::BuiltinType::Double:
-      content = "f64";
-      break;
-    case clang::BuiltinType::Void:
-      content = "()";
-      break;
-    default:
-      // In this case we do not know what the output should be so we do not
-      // write any.
-      return true;
-  }
-  SetReplacement(type_loc, OutputSegment(content));
-  return true;
-}
-
-auto RewriteBuilder::VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr* expr)
-    -> bool {
-  SetReplacement(expr, OutputSegment(expr->getValue() ? "true" : "false"));
-  return true;
-}
-
-auto RewriteBuilder::VisitDeclRefExpr(clang::DeclRefExpr* expr) -> bool {
-  SetReplacement(expr, OutputSegment(TextForTokenAt(expr->getBeginLoc())));
-  return true;
-}
-
-auto RewriteBuilder::VisitDeclStmt(clang::DeclStmt* stmt) -> bool {
-  std::vector<OutputSegment> segments;
-  for (clang::Decl* decl : stmt->decls()) {
-    segments.push_back(OutputSegment(decl));
-    segments.push_back(OutputSegment(";\n"));
-  }
-  SetReplacement(stmt, std::move(segments));
-  return true;
-}
-
-auto RewriteBuilder::VisitImplicitCastExpr(clang::ImplicitCastExpr* expr)
-    -> bool {
-  SetReplacement(expr, OutputSegment(expr->getSubExpr()));
-  return true;
-}
-
-auto RewriteBuilder::VisitIntegerLiteral(clang::IntegerLiteral* expr) -> bool {
-  // TODO: Replace suffixes.
-  std::string text(TextForTokenAt(expr->getBeginLoc()));
-  for (char& c : text) {
-    // Carbon uses underscores for digit separators whereas C++ uses single
-    // quotation marks. Convert all `'` to `_`.
-    if (c == '\'') {
-      c = '_';
-    }
-  }
-  SetReplacement(expr, OutputSegment(std::move(text)));
-  return true;
-}
-
-auto RewriteBuilder::VisitParmVarDecl(clang::ParmVarDecl* decl) -> bool {
-  llvm::StringRef name = decl->getName();
-  std::vector<OutputSegment> segments = {
-      OutputSegment(llvm::formatv("{0}: ", name.empty() ? "_" : name.str())),
-      OutputSegment(decl->getTypeSourceInfo()->getTypeLoc()),
-  };
-
-  if (clang::Expr* init = decl->getInit()) {
-    segments.push_back(OutputSegment(" = "));
-    segments.push_back(OutputSegment(init));
-  }
-
-  SetReplacement(decl, std::move(segments));
-  return true;
-}
-
-auto RewriteBuilder::VisitPointerTypeLoc(clang::PointerTypeLoc type_loc)
-    -> bool {
-  SetReplacement(type_loc,
-                 {OutputSegment(type_loc.getPointeeLoc()), OutputSegment("*")});
-  return true;
-}
-
-auto RewriteBuilder::VisitReturnStmt(clang::ReturnStmt* stmt) -> bool {
-  SetReplacement(
-      stmt, {OutputSegment("return "), OutputSegment(stmt->getRetValue())});
-  return true;
-}
-
-auto RewriteBuilder::VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl)
-    -> bool {
-  std::vector<OutputSegment> segments;
-
-  // Clang starts each translation unit with some initial `TypeDefDecl`s that
-  // are not part of the written text. We want to skip past these initial
-  // declarations, which we do by ignoring any node of type `TypeDefDecl` which
-  // has an invalid source location.
-  auto iter = decl->decls_begin();
-  while (iter != decl->decls_end() && llvm::isa<clang::TypedefDecl>(*iter) &&
-         (*iter)->getLocation().isInvalid()) {
-    ++iter;
-  }
-
-  for (; iter != decl->decls_end(); ++iter) {
-    clang::Decl* d = *iter;
-    segments.push_back(OutputSegment(d));
-
-    // Function definitions do not need semicolons.
-    bool needs_semicolon = !(llvm::isa<clang::FunctionDecl>(d) &&
-                             llvm::cast<clang::FunctionDecl>(d)->hasBody());
-    segments.push_back(OutputSegment(needs_semicolon ? ";\n" : "\n"));
-  }
-
-  SetReplacement(decl, std::move(segments));
-  return true;
-}
-
-auto RewriteBuilder::VisitUnaryOperator(clang::UnaryOperator* expr) -> bool {
-  switch (expr->getOpcode()) {
-    case clang::UO_AddrOf:
-      SetReplacement(expr,
-                     {OutputSegment("&"), OutputSegment(expr->getSubExpr())});
-      break;
-
-    default:
-      // TODO: Finish implementing cases.
-      break;
-  }
-  return true;
-}
-
-// NOLINTNEXTLINE(misc-no-recursion): Recursion may be okay for migration.
-auto RewriteBuilder::TraverseFunctionDecl(clang::FunctionDecl* decl) -> bool {
-  clang::TypeLoc return_type_loc = decl->getFunctionTypeLoc().getReturnLoc();
-  if (!TraverseTypeLoc(return_type_loc)) {
-    return false;
-  }
-
-  std::vector<OutputSegment> segments;
-  segments.push_back(
-      OutputSegment(llvm::formatv("fn {0}(", decl->getNameAsString())));
-
-  size_t i = 0;
-  for (; i + 1 < decl->getNumParams(); ++i) {
-    clang::ParmVarDecl* param = decl->getParamDecl(i);
-    if (!TraverseDecl(param)) {
-      return false;
-    }
-    segments.push_back(OutputSegment(param));
-    segments.push_back(OutputSegment(", "));
-  }
-
-  if (i + 1 == decl->getNumParams()) {
-    clang::ParmVarDecl* param = decl->getParamDecl(i);
-    if (!TraverseDecl(param)) {
-      return false;
-    }
-    segments.push_back(OutputSegment(param));
-  }
-
-  segments.push_back(OutputSegment(") -> "));
-  segments.push_back(OutputSegment(return_type_loc));
-
-  if (decl->hasBody()) {
-    segments.push_back(OutputSegment(" {\n"));
-    auto* stmts = llvm::dyn_cast<clang::CompoundStmt>(decl->getBody());
-    for (clang::Stmt* stmt : stmts->body()) {
-      if (!TraverseStmt(stmt)) {
-        return false;
-      }
-      segments.push_back(OutputSegment(stmt));
-      segments.push_back(OutputSegment(";\n"));
-    }
-    segments.push_back(OutputSegment("}"));
-  }
-
-  SetReplacement(decl, std::move(segments));
-  return true;
-}
-
-// NOLINTNEXTLINE(misc-no-recursion): Recursion may be okay for migration.
-auto RewriteBuilder::TraverseVarDecl(clang::VarDecl* decl) -> bool {
-  clang::TypeLoc loc = decl->getTypeSourceInfo()->getTypeLoc();
-  if (!TraverseTypeLoc(loc)) {
-    return false;
-  }
-
-  // TODO: Check storage class. Determine what happens for static local
-  // variables.
-  bool is_const = decl->getType().isConstQualified();
-  std::vector<OutputSegment> segments = {
-      OutputSegment(llvm::formatv("{0} {1}: ", is_const ? "let" : "var",
-                                  decl->getNameAsString())),
-      OutputSegment(decl->getTypeSourceInfo()->getTypeLoc()),
-  };
-
-  if (clang::Expr* init = decl->getInit()) {
-    if (!TraverseStmt(init)) {
-      return false;
-    }
-
-    segments.push_back(OutputSegment(" = "));
-    segments.push_back(OutputSegment(init));
-  }
-
-  SetReplacement(decl, std::move(segments));
-  return true;
-}
-
-}  // namespace Carbon

+ 0 - 223
migrate_cpp/rewriter.h

@@ -1,223 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#ifndef CARBON_MIGRATE_CPP_REWRITER_H_
-#define CARBON_MIGRATE_CPP_REWRITER_H_
-
-#include <string>
-#include <utility>
-#include <variant>
-#include <vector>
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "llvm/ADT/DenseMap.h"
-#include "migrate_cpp/output_segment.h"
-
-namespace Carbon {
-namespace Internal {
-
-struct Empty {
-  friend auto operator==(Empty /*unused*/, Empty /*unused*/) -> bool {
-    return true;
-  }
-};
-struct Tombstone {
-  friend auto operator==(Tombstone /*unused*/, Tombstone /*unused*/) -> bool {
-    return true;
-  }
-};
-
-// Type alias for the variant representing any of the values that can be
-// written with OutputWriter.
-using KeyType =
-    std::variant<clang::DynTypedNode, clang::TypeLoc, Empty, Tombstone>;
-
-// `KeyInfo` is used as a template argument to `llvm::DenseMap` to specify how
-// to equality-compare and hash `KeyType`.
-struct KeyInfo {
-  static auto isEqual(const KeyType& lhs, const KeyType& rhs) -> bool {
-    return lhs == rhs;
-  }
-  static auto getHashValue(const KeyType& x) -> unsigned {
-    return std::visit(
-        [](auto x) -> unsigned {
-          using Type = std::decay_t<decltype(x)>;
-          if constexpr (std::is_same_v<Type, clang::DynTypedNode>) {
-            return clang::DynTypedNode::DenseMapInfo::getHashValue(x);
-          } else if constexpr (std::is_same_v<Type, clang::TypeLoc>) {
-            // TODO: Improve this.
-            return reinterpret_cast<uintptr_t>(x.getTypePtr());
-          } else {
-            return 0;
-          }
-        },
-        x);
-  }
-
-  static auto getEmptyKey() -> KeyType { return Empty{}; }
-  static auto getTombstoneKey() -> KeyType { return Tombstone{}; }
-};
-
-}  // namespace Internal
-
-// `OutputWriter` is responsible for traversing the tree of `OutputSegment`s
-// and writing the correct data to its member `output`.
-struct OutputWriter {
-  using SegmentMapType =
-      llvm::DenseMap<Internal::KeyType, std::vector<OutputSegment>,
-                     Internal::KeyInfo>;
-
-  auto Write(clang::SourceLocation loc, const OutputSegment& segment) const
-      -> bool;
-
-  const SegmentMapType& map;
-
-  // Bounds represent the offsets into the primary file (multi-file refactorings
-  // are not yet supported) that should be output. While primarily this is a
-  // mechanism to make testing more robust, it can also be used to make local
-  // changes to sections of C++ code.
-  std::pair<size_t, size_t> bounds;
-
-  clang::SourceManager& source_manager;
-  std::string& output;
-};
-
-// `RewriteBuilder` is a recursive AST visitor. For each node, it computes and
-// stores a sequence of `OutputSegment`s describing how this node should be
-// replaced.
-class RewriteBuilder : public clang::RecursiveASTVisitor<RewriteBuilder> {
- public:
-  using SegmentMapType = typename OutputWriter::SegmentMapType;
-
-  // Constructs a `RewriteBuilder` which can read the AST from `context` and
-  // will write results into `segments`.
-  explicit RewriteBuilder(clang::ASTContext& context, SegmentMapType& segments)
-      : context_(context), segments_(segments) {}
-
-  // By default, traverse children nodes before their parent. Called by the CRTP
-  // base class to determine traversal order.
-  auto shouldTraversePostOrder() const -> bool { return true; }
-
-  // Visitor member functions, defining how each node should be processed.
-  auto VisitBuiltinTypeLoc(clang::BuiltinTypeLoc type_loc) -> bool;
-  auto VisitCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr* expr) -> bool;
-  auto VisitDeclRefExpr(clang::DeclRefExpr* expr) -> bool;
-  auto VisitDeclStmt(clang::DeclStmt* stmt) -> bool;
-  auto VisitImplicitCastExpr(clang::ImplicitCastExpr* expr) -> bool;
-  auto VisitIntegerLiteral(clang::IntegerLiteral* expr) -> bool;
-  auto VisitParmVarDecl(clang::ParmVarDecl* decl) -> bool;
-  auto VisitPointerTypeLoc(clang::PointerTypeLoc type_loc) -> bool;
-  auto VisitReturnStmt(clang::ReturnStmt* stmt) -> bool;
-  auto VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl) -> bool;
-  auto VisitUnaryOperator(clang::UnaryOperator* expr) -> bool;
-
-  auto TraverseFunctionDecl(clang::FunctionDecl* decl) -> bool;
-  auto TraverseVarDecl(clang::VarDecl* decl) -> bool;
-
-  auto segments() const -> const SegmentMapType& { return segments_; }
-  auto segments() -> SegmentMapType& { return segments_; }
-
- private:
-  // Associates `output_segments` in the output map `this->segments()` with the
-  // key `node`, so as to declare that, when output is being written, `node`
-  // should be replaced with the sequence of outputs described by
-  // `output_segments`.
-  auto SetReplacement(clang::DynTypedNode node,
-                      std::vector<OutputSegment> output_segments) -> void {
-    segments_.try_emplace(node, std::move(output_segments));
-  }
-
-  auto SetReplacement(clang::TypeLoc node,
-                      std::vector<OutputSegment> output_segments) -> void {
-    segments_.try_emplace(node, std::move(output_segments));
-  }
-
-  template <typename T>
-  auto SetReplacement(const T* node, std::vector<OutputSegment> output_segments)
-      -> void {
-    segments_.try_emplace(clang::DynTypedNode::create(*node),
-                          std::move(output_segments));
-  }
-
-  // Invokes the overload of `SetReplacement` defined above. Equivalent to
-  // `this->SetReplacement(node, std::vector<OutputSegment>(1, segment))`.
-  template <typename T>
-  auto SetReplacement(const T* node, OutputSegment segment) -> void {
-    std::vector<OutputSegment> node_segments;
-    node_segments.push_back(std::move(segment));
-    SetReplacement(node, std::move(node_segments));
-  }
-
-  auto SetReplacement(clang::TypeLoc type_loc, OutputSegment segment) -> void {
-    std::vector<OutputSegment> node_segments;
-    node_segments.push_back(std::move(segment));
-    SetReplacement(type_loc, std::move(node_segments));
-  }
-
-  // Returns a `llvm::StringRef` into the source text corresponding to the
-  // half-open interval starting at `begin` (inclusive) and ending at `end`
-  // (exclusive).
-  auto TextFor(clang::SourceLocation begin, clang::SourceLocation end) const
-      -> llvm::StringRef;
-
-  // Returns a `llvm::StringRef` into the source text for the single token
-  // located at `loc`.
-  auto TextForTokenAt(clang::SourceLocation loc) const -> llvm::StringRef;
-
-  clang::ASTContext& context_;
-  SegmentMapType& segments_;
-};
-
-// An `ASTConsumer` which, when executed, populates a `std::string` with the
-// text of a Carbon source file which is a best approximation of the
-// semantics of the corresponding C++ translation unit defined by the consumed
-// AST.
-class MigrationConsumer : public clang::ASTConsumer {
- public:
-  explicit MigrationConsumer(std::string& result,
-                             std::pair<size_t, size_t> output_range)
-      : result_(result), output_range_(std::move(output_range)) {}
-
-  auto HandleTranslationUnit(clang::ASTContext& context) -> void override;
-
- private:
-  RewriteBuilder::SegmentMapType segment_map_;
-  std::string& result_;
-  std::pair<size_t, size_t> output_range_;
-};
-
-// An `ASTFrontendAction` which constructs a `MigrationConsumer` and invokes it
-// on an AST, populating a `std::string` with the text of a Carbon source file
-// which is a best approximation of the semantics of the corresponding C++
-// translation unit defined by the consumed AST.
-class MigrationAction : public clang::ASTFrontendAction {
- public:
-  // Constructs the `MigrationAction`. The parameter `result` is a reference to
-  // the `std::string` where output will be written. Only output corresponding
-  // to text at offsets that fall in between `output_range.first` and
-  // `output_range.second` will be written.
-  explicit MigrationAction(std::string& result,
-                           std::pair<size_t, size_t> output_range)
-      : result_(result), output_range_(std::move(output_range)) {}
-
-  // Returns a `std::unique_ptr` to a `clang::MigrationConsumer` which populates
-  // the output `result`.
-  auto CreateASTConsumer(clang::CompilerInstance& /*CI*/,
-                         llvm::StringRef /*InFile*/)
-      -> std::unique_ptr<clang::ASTConsumer> override {
-    return std::make_unique<MigrationConsumer>(result_, output_range_);
-  }
-
- private:
-  std::string& result_;
-  std::pair<size_t, size_t> output_range_;
-};
-
-}  // namespace Carbon
-
-#endif  // CARBON_MIGRATE_CPP_REWRITER_H_

+ 0 - 190
migrate_cpp/rewriter_test.cpp

@@ -1,190 +0,0 @@
-// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
-// Exceptions. See /LICENSE for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-#include "migrate_cpp/rewriter.h"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/FrontendAction.h"
-#include "clang/Tooling/Tooling.h"
-
-namespace Carbon::Testing {
-namespace {
-
-// Represents C++ source code with at most one region enclosed in $[[...]]$ as
-// an annotated range.
-class Annotations {
- public:
-  explicit Annotations(llvm::StringRef annotated_source) {
-    size_t index = annotated_source.find("$[[");
-    if (index == llvm::StringRef::npos) {
-      source_code_ = std::string(annotated_source);
-      return;
-    }
-    start_ = index;
-    end_ = annotated_source.find("]]$", index);
-    CARBON_CHECK(end_ != llvm::StringRef::npos,
-                 "Found `$[[` but no matching `]]$`");
-    source_code_ = (llvm::Twine(annotated_source.substr(0, start_)) +
-                    annotated_source.substr(start_ + 3, end_ - start_ - 3) +
-                    annotated_source.substr(end_ + 3))
-                       .str();
-    // Update `end_` so that it is relative to the unannotated source (which
-    // means three characters earlier due to the `$[[` being removed.
-    end_ -= 3;
-  }
-
-  // Returns a view into the unannotated source.
-  auto source() const -> llvm::StringRef { return source_code_; }
-
-  // Returns the offsets in the file representing the annotated range if they
-  // exist and `{0, std::numeric_limits<size_t>::max()}` otherwise.
-  auto range() const -> std::pair<size_t, size_t> {
-    return std::pair(start_, end_);
-  }
-
- private:
-  std::string source_code_;
-  size_t start_ = 0;
-  size_t end_ = std::numeric_limits<size_t>::max();
-};
-
-// Rewrites the `cpp_code`, return the Carbon equivalent. If the text has no
-// source range annotated with $[[...]]$, the entire translation unit will be
-// migrated and output. Otherwise, only the migrated output corresponding to the
-// annotated range will be output. No more than one range may be annotated at
-// all.
-//
-// This annotation mechanism is useful in that it allows us to specifically test
-// the migration associated with specific nodes even when they require some
-// additional context that we do not wish to be covered by the test.
-auto RewriteText(llvm::StringRef cpp_code) -> std::string {
-  std::string result;
-
-  Annotations annotated_cpp_code(cpp_code);
-
-  bool success = clang::tooling::runToolOnCodeWithArgs(
-      std::make_unique<MigrationAction>(result, annotated_cpp_code.range()),
-      annotated_cpp_code.source(), {}, "test.cc", "clang-tool",
-      std::make_shared<clang::PCHContainerOperations>(),
-      clang::tooling::FileContentMappings());
-
-  return success ? result : "";
-}
-
-TEST(Rewriter, BoolLiteral) {
-  EXPECT_EQ(RewriteText("bool x = $[[true]]$;"), "true");
-  EXPECT_EQ(RewriteText("bool x = $[[false]]$;"), "false");
-}
-
-TEST(Rewriter, IntegerLiteral) {
-  EXPECT_EQ(RewriteText("int x = $[[0]]$;"), "0");
-  EXPECT_EQ(RewriteText("int x = $[[1]]$;"), "1");
-  EXPECT_EQ(RewriteText("int x = $[[1234]]$;"), "1234");
-  EXPECT_EQ(RewriteText("int x = $[[12'34]]$;"), "12_34");
-  EXPECT_EQ(RewriteText("int x = $[[12'3'4]]$;"), "12_3_4");
-}
-
-TEST(Rewriter, SingleDeclaration) {
-  EXPECT_EQ(RewriteText("bool b;"), "var b: bool;\n");
-  EXPECT_EQ(RewriteText("int i;"), "var i: i32;\n");
-
-  EXPECT_EQ(RewriteText("const bool b = false;"), "let b: bool = false;\n");
-  EXPECT_EQ(RewriteText("const int i = 17;"), "let i: i32 = 17;\n");
-
-  EXPECT_EQ(RewriteText("bool const b = false;"), "let b: bool = false;\n");
-  EXPECT_EQ(RewriteText("int const i = 1234;"), "let i: i32 = 1234;\n");
-}
-
-TEST(Rewriter, Pointers) {
-  // TODO: Add tests for pointers-to-const when the syntax is nailed down.
-  EXPECT_EQ(RewriteText("bool b;\n"
-                        "$[[bool *p = &b]]$;"),
-            "var p: bool* = &b");
-  EXPECT_EQ(RewriteText("bool b;\n"
-                        "$[[bool * const p = &b]]$;"),
-            "let p: bool* = &b");
-
-  // Pointers and non-pointers on the same DeclStmt.
-  EXPECT_EQ(RewriteText("bool b, *p;\n"),
-            "var b: bool;\n"
-            "var p: bool*;\n");
-  EXPECT_EQ(RewriteText("bool b, *p = &b;\n"),
-            "var b: bool;\n"
-            "var p: bool* = &b;\n");
-}
-
-TEST(Rewriter, DeclarationComma) {
-  EXPECT_EQ(RewriteText("int x, y;"),
-            "var x: i32;\n"
-            "var y: i32;\n");
-  EXPECT_EQ(RewriteText("int x = 7, y;"),
-            "var x: i32 = 7;\n"
-            "var y: i32;\n");
-  EXPECT_EQ(RewriteText("const int x = 1, y = 2;"),
-            "let x: i32 = 1;\n"
-            "let y: i32 = 2;\n");
-  EXPECT_EQ(RewriteText("int const x = 1234, y = 5678;"),
-            "let x: i32 = 1234;\n"
-            "let y: i32 = 5678;\n");
-}
-
-TEST(Rewriter, FunctionDeclaration) {
-  // Function declarations and definitions returning void.
-  EXPECT_EQ(RewriteText("void f();"), "fn f() -> ();\n");
-  EXPECT_EQ(RewriteText("void f() {}"),
-            "fn f() -> () {\n"
-            "}\n");
-
-  // Function declarations and definitions returning int.
-  EXPECT_EQ(RewriteText("int f();"), "fn f() -> i32;\n");
-  EXPECT_EQ(RewriteText("int f() { return 0; }"),
-            "fn f() -> i32 {\n"
-            "return 0;\n"
-            "}\n");
-
-  // Function declarations and definitions with a single parameter.
-  EXPECT_EQ(RewriteText("int f(bool);"), "fn f(_: bool) -> i32;\n");
-  EXPECT_EQ(RewriteText("int f(bool b);"), "fn f(b: bool) -> i32;\n");
-  EXPECT_EQ(RewriteText("int f(bool) { return 0; }"),
-            "fn f(_: bool) -> i32 {\n"
-            "return 0;\n"
-            "}\n");
-  EXPECT_EQ(RewriteText("int f(bool b) { return 0; }"),
-            "fn f(b: bool) -> i32 {\n"
-            "return 0;\n"
-            "}\n");
-
-  // Function declarations and definitions with a multiple parameters.
-  EXPECT_EQ(RewriteText("int f(bool, int);"),
-            "fn f(_: bool, _: i32) -> i32;\n");
-  EXPECT_EQ(RewriteText("int f(bool b, int n);"),
-            "fn f(b: bool, n: i32) -> i32;\n");
-  EXPECT_EQ(RewriteText("int f(bool, int n) { return 0; }"),
-            "fn f(_: bool, n: i32) -> i32 {\n"
-            "return 0;\n"
-            "}\n");
-  EXPECT_EQ(RewriteText("int f(bool b, int n) { return 0; }"),
-            "fn f(b: bool, n: i32) -> i32 {\n"
-            "return 0;\n"
-            "}\n");
-  EXPECT_EQ(RewriteText("int f(bool b, int n = 3) { return n; }"),
-            "fn f(b: bool, n: i32 = 3) -> i32 {\n"
-            "return n;\n"
-            "}\n");
-
-  // Function declarations with trailing-return syntax.
-  EXPECT_EQ(RewriteText("auto f(bool b, int n = 3) -> int;"),
-            "fn f(b: bool, n: i32 = 3) -> i32;\n");
-  EXPECT_EQ(RewriteText("auto f(bool b, int n = 3) -> int { return n; }"),
-            "fn f(b: bool, n: i32 = 3) -> i32 {\n"
-            "return n;\n"
-            "}\n");
-}
-
-}  // namespace
-}  // namespace Carbon::Testing