Use AST to start inserting fn (#530)

This commit is contained in:
Jon Meow
2021-05-13 14:58:32 -07:00
committed by GitHub
parent 2942c97424
commit 6f544494b3
36 changed files with 297 additions and 162 deletions
+1
View File
@@ -9,6 +9,7 @@ py_binary(
srcs = ["migrate_cpp.py"],
data = [
":clang_tidy.yaml",
"//migrate_cpp/cpp_refactoring",
"@bootstrap_clang_toolchain//:bin/clang-tidy",
],
python_version = "PY3",
+16
View File
@@ -0,0 +1,16 @@
# 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")
package(default_visibility = ["//visibility:public"])
cc_binary(
name = "cpp_refactoring",
srcs = ["main.cpp"],
deps = [
"@llvm-project//clang:ast_matchers",
"@llvm-project//clang:tooling",
],
)
+96
View File
@@ -0,0 +1,96 @@
// 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/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Refactoring.h"
namespace cam = ::clang::ast_matchers;
namespace ct = ::clang::tooling;
namespace carbon {
class Matcher : public cam::MatchFinder::MatchCallback {
public:
explicit Matcher(std::map<std::string, ct::Replacements>* in_replacements)
: replacements(in_replacements) {}
virtual ~Matcher() {}
void AddReplacement(const clang::SourceManager& sm,
clang::CharSourceRange range,
llvm::StringRef replacement_text) {
if (!range.isValid()) {
llvm::errs() << "Invalid range: " << range.getAsRange().printToString(sm)
<< "\n";
return;
}
if (sm.getDecomposedLoc(range.getBegin()).first !=
sm.getDecomposedLoc(range.getEnd()).first) {
llvm::errs() << "Range spans macro expansions: "
<< range.getAsRange().printToString(sm) << "\n";
return;
}
if (sm.getFileID(range.getBegin()) != sm.getFileID(range.getEnd())) {
llvm::errs() << "Range spans files: "
<< range.getAsRange().printToString(sm) << "\n";
return;
}
auto rep =
ct::Replacement(sm, sm.getExpansionRange(range), replacement_text);
auto err = (*replacements)[std::string(rep.getFilePath())].add(rep);
if (err) {
llvm::report_fatal_error("Error with replacement `" + rep.toString() +
"`: " + llvm::toString(std::move(err)) + "\n");
}
}
private:
std::map<std::string, ct::Replacements>* replacements;
};
class FnInserter : public Matcher {
public:
explicit FnInserter(std::map<std::string, ct::Replacements>* in_replacements,
cam::MatchFinder* finder)
: Matcher(in_replacements) {
finder->addMatcher(cam::functionDecl(cam::isExpansionInMainFile(),
cam::hasTrailingReturn())
.bind(Label),
this);
}
void run(const cam::MatchFinder::MatchResult& result) override {
// The matched 'if' statement was bound to 'ifStmt'.
const auto* decl = result.Nodes.getNodeAs<clang::FunctionDecl>(Label);
if (!decl) {
llvm::report_fatal_error(std::string("getNodeAs failed for ") + Label);
}
auto begin = decl->getBeginLoc();
// Replace the first token in the range, `auto`.
auto range = clang::CharSourceRange::getTokenRange(begin, begin);
AddReplacement(*(result.SourceManager), range, "fn");
}
private:
static constexpr char Label[] = "FnInserter";
};
} // namespace carbon
auto main(int argc, const char** argv) -> int {
llvm::cl::OptionCategory category("C++ refactoring options");
clang::tooling::CommonOptionsParser op(argc, argv, category);
clang::tooling::RefactoringTool tool(op.getCompilations(),
op.getSourcePathList());
// Set up AST matcher callbacks.
cam::MatchFinder finder;
carbon::FnInserter fn_inserter(&tool.getReplacements(), &finder);
return tool.runAndSave(
clang::tooling::newFrontendActionFactory(&finder).get());
}
+9
View File
@@ -13,6 +13,7 @@ import subprocess
import sys
_CLANG_TIDY = "../external/bootstrap_clang_toolchain/bin/clang-tidy"
_CPP_REFACTORING = "./cpp_refactoring/cpp_refactoring"
_CPP_EXTS = {".h", ".c", ".cc", ".cpp", ".cxx"}
@@ -55,6 +56,13 @@ def _clang_tidy(parsed_args, cpp_files):
subprocess.run([clang_tidy, "--fix", "--config", config] + cpp_files)
def _cpp_refactoring(parsed_args, cpp_files):
"""Runs cpp_refactoring to migrate C++ files towards Carbon syntax."""
print("Running cpp_refactoring...")
cpp_refactoring = _data_file(_CPP_REFACTORING)
subprocess.run([cpp_refactoring] + cpp_files)
def _main():
"""Main program execution."""
parsed_args = _parse_args()
@@ -65,6 +73,7 @@ def _main():
cpp_files = _gather_files(parsed_args)
_clang_tidy(parsed_args, cpp_files)
_cpp_refactoring(parsed_args, cpp_files)
print("Done!")