ClangTidyProfiling.cpp 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. //===--- ClangTidyProfiling.cpp - clang-tidy --------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "ClangTidyProfiling.h"
  9. #include "llvm/ADT/SmallString.h"
  10. #include "llvm/Support/FileSystem.h"
  11. #include "llvm/Support/Path.h"
  12. #include "llvm/Support/raw_ostream.h"
  13. #include <optional>
  14. #include <system_error>
  15. #include <utility>
  16. #define DEBUG_TYPE "clang-tidy-profiling"
  17. namespace clang::tidy {
  18. ClangTidyProfiling::StorageParams::StorageParams(llvm::StringRef ProfilePrefix,
  19. llvm::StringRef SourceFile)
  20. : Timestamp(std::chrono::system_clock::now()), SourceFilename(SourceFile) {
  21. llvm::SmallString<32> TimestampStr;
  22. llvm::raw_svector_ostream OS(TimestampStr);
  23. llvm::format_provider<decltype(Timestamp)>::format(Timestamp, OS,
  24. "%Y%m%d%H%M%S%N");
  25. llvm::SmallString<256> FinalPrefix(ProfilePrefix);
  26. llvm::sys::path::append(FinalPrefix, TimestampStr);
  27. // So the full output name is: /ProfilePrefix/timestamp-inputfilename.json
  28. StoreFilename = llvm::Twine(FinalPrefix + "-" +
  29. llvm::sys::path::filename(SourceFile) + ".json")
  30. .str();
  31. }
  32. void ClangTidyProfiling::printUserFriendlyTable(llvm::raw_ostream &OS) {
  33. TG->print(OS);
  34. OS.flush();
  35. }
  36. void ClangTidyProfiling::printAsJSON(llvm::raw_ostream &OS) {
  37. OS << "{\n";
  38. OS << "\"file\": \"" << Storage->SourceFilename << "\",\n";
  39. OS << "\"timestamp\": \"" << Storage->Timestamp << "\",\n";
  40. OS << "\"profile\": {\n";
  41. TG->printJSONValues(OS, "");
  42. OS << "\n}\n";
  43. OS << "}\n";
  44. OS.flush();
  45. }
  46. void ClangTidyProfiling::storeProfileData() {
  47. assert(Storage && "We should have a filename.");
  48. llvm::SmallString<256> OutputDirectory(Storage->StoreFilename);
  49. llvm::sys::path::remove_filename(OutputDirectory);
  50. if (std::error_code EC = llvm::sys::fs::create_directories(OutputDirectory)) {
  51. llvm::errs() << "Unable to create output directory '" << OutputDirectory
  52. << "': " << EC.message() << "\n";
  53. return;
  54. }
  55. std::error_code EC;
  56. llvm::raw_fd_ostream OS(Storage->StoreFilename, EC, llvm::sys::fs::OF_None);
  57. if (EC) {
  58. llvm::errs() << "Error opening output file '" << Storage->StoreFilename
  59. << "': " << EC.message() << "\n";
  60. return;
  61. }
  62. printAsJSON(OS);
  63. }
  64. ClangTidyProfiling::ClangTidyProfiling(std::optional<StorageParams> Storage)
  65. : Storage(std::move(Storage)) {}
  66. ClangTidyProfiling::~ClangTidyProfiling() {
  67. TG.emplace("clang-tidy", "clang-tidy checks profiling", Records);
  68. if (!Storage)
  69. printUserFriendlyTable(llvm::errs());
  70. else
  71. storeProfileData();
  72. }
  73. } // namespace clang::tidy