From fb98b74f8e20c56776c7f1147c755d8bd01ee8a7 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Thu, 4 Sep 2014 10:31:23 +0000 Subject: [PATCH] [clang-tidy] Add an option to export suggested fixes into a file. Allows gathering fixes and applying them with clang-apply-fixes. Differential Revision: http://reviews.llvm.org/D5176 llvm-svn: 217139 --- clang-tools-extra/clang-tidy/ClangTidy.cpp | 12 ++++++++++++ clang-tools-extra/clang-tidy/ClangTidy.h | 5 +++++ .../clang-tidy/tool/ClangTidyMain.cpp | 17 +++++++++++++++++ clang-tools-extra/test/clang-tidy/fix.cpp | 5 ++++- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index f74077037d2f..ccf56f6fa3a9 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -34,6 +34,7 @@ #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h" #include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/ReplacementsYaml.h" #include "clang/Tooling/Tooling.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -362,5 +363,16 @@ void handleErrors(const std::vector &Errors, bool Fix) { Reporter.Finish(); } +void exportReplacements(const std::vector &Errors, + raw_ostream &OS) { + tooling::TranslationUnitReplacements TUR; + for (const ClangTidyError &Error : Errors) + TUR.Replacements.insert(TUR.Replacements.end(), Error.Fix.begin(), + Error.Fix.end()); + + yaml::Output YAML(OS); + YAML << TUR; +} + } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/ClangTidy.h b/clang-tools-extra/clang-tidy/ClangTidy.h index 9486577f2a2a..1112bf1b3e5f 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.h +++ b/clang-tools-extra/clang-tidy/ClangTidy.h @@ -133,6 +133,11 @@ runClangTidy(ClangTidyOptionsProvider *OptionsProvider, /// Errors containing fixes are automatically applied. void handleErrors(const std::vector &Errors, bool Fix); +/// \brief Serializes replacements into YAML and writes them to the specified +/// output stream. +void exportReplacements(const std::vector &Errors, + raw_ostream &OS); + } // end namespace tidy } // end namespace clang diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index 030e4b163987..d49994d2f417 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -78,6 +78,13 @@ AnalyzeTemporaryDtors("analyze-temporary-dtors", "clang-analyzer- checks."), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt ExportFixes( + "export-fixes", + cl::desc("YAML file to store suggested fixes in. The\n" + "stored fixes can be applied to the input source\n" + "code with clang-apply-replacements."), + cl::value_desc("filename"), cl::cat(ClangTidyCategory)); + static void printStats(const clang::tidy::ClangTidyStats &Stats) { if (Stats.errorsIgnored()) { llvm::errs() << "Suppressed " << Stats.errorsIgnored() << " warnings ("; @@ -147,6 +154,16 @@ int main(int argc, const char **argv) { OptionsParser.getSourcePathList(), &Errors); clang::tidy::handleErrors(Errors, Fix); + if (!ExportFixes.empty()) { + std::error_code EC; + llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); + if (EC) { + llvm::errs() << "Error opening output file: " << EC.message() << '\n'; + return 1; + } + clang::tidy::exportReplacements(Errors, OS); + } + printStats(Stats); return 0; } diff --git a/clang-tools-extra/test/clang-tidy/fix.cpp b/clang-tools-extra/test/clang-tidy/fix.cpp index f82ed0b16701..80b215d82b83 100644 --- a/clang-tools-extra/test/clang-tidy/fix.cpp +++ b/clang-tools-extra/test/clang-tidy/fix.cpp @@ -1,14 +1,17 @@ // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp -// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor,llvm-namespace-comment' -fix -- > %t.msg 2>&1 +// RUN: clang-tidy %t.cpp -checks='-*,google-explicit-constructor,llvm-namespace-comment' -fix -export-fixes=%t.yaml -- > %t.msg 2>&1 // RUN: FileCheck -input-file=%t.cpp %s // RUN: FileCheck -input-file=%t.msg -check-prefix=CHECK-MESSAGES %s +// RUN: FileCheck -input-file=%t.yaml -check-prefix=CHECK-YAML %s namespace i { } // CHECK: } // namespace i // CHECK-MESSAGES: note: FIX-IT applied suggested code changes +// CHECK-YAML: ReplacementText: ' // namespace i' class A { A(int i); }; // CHECK: class A { explicit A(int i); }; // CHECK-MESSAGES: note: FIX-IT applied suggested code changes // CHECK-MESSAGES: clang-tidy applied 2 of 2 suggested fixes. +// CHECK-YAML: ReplacementText: 'explicit '