1 //===-- ApplyReplacements.h - Deduplicate and apply replacements -- 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 /// 9 /// \file 10 /// This file provides the interface for deduplicating, detecting 11 /// conflicts in, and applying collections of Replacements. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_APPLYREPLACEMENTS_H 16 #define LLVM_CLANG_APPLYREPLACEMENTS_H 17 18 #include "clang/Tooling/Core/Diagnostic.h" 19 #include "clang/Tooling/Refactoring.h" 20 #include "clang/Tooling/Refactoring/AtomicChange.h" 21 #include "llvm/ADT/StringMap.h" 22 #include "llvm/ADT/StringRef.h" 23 #include <string> 24 #include <system_error> 25 #include <vector> 26 27 namespace clang { 28 29 class DiagnosticsEngine; 30 31 namespace replace { 32 33 /// Collection of TranslationUnitReplacements. 34 typedef std::vector<clang::tooling::TranslationUnitReplacements> TUReplacements; 35 36 /// Collection of TranslationUnitReplacement files. 37 typedef std::vector<std::string> TUReplacementFiles; 38 39 /// Collection of TranslationUniDiagnostics. 40 typedef std::vector<clang::tooling::TranslationUnitDiagnostics> TUDiagnostics; 41 42 /// Map mapping file name to a set of AtomicChange targeting that file. 43 using FileToChangesMap = 44 llvm::DenseMap<clang::FileEntryRef, std::vector<tooling::AtomicChange>>; 45 46 /// Recursively descends through a directory structure rooted at \p 47 /// Directory and attempts to deserialize *.yaml files as 48 /// TranslationUnitReplacements. All docs that successfully deserialize are 49 /// added to \p TUs. 50 /// 51 /// Directories starting with '.' are ignored during traversal. 52 /// 53 /// \param[in] Directory Directory to begin search for serialized 54 /// TranslationUnitReplacements or TranslationUnitDiagnostics. 55 /// \param[out] TUs Collection of all found and deserialized 56 /// TranslationUnitReplacements or TranslationUnitDiagnostics. 57 /// \param[out] TUFiles Collection of all TranslationUnitReplacement or 58 /// TranslationUnitDiagnostics files found in \c Directory. 59 /// \param[in] Diagnostics DiagnosticsEngine used for error output. 60 /// 61 /// \returns An error_code indicating success or failure in navigating the 62 /// directory structure. 63 template <typename TranslationUnits> 64 std::error_code collectReplacementsFromDirectory( 65 const llvm::StringRef Directory, TranslationUnits &TUs, 66 TUReplacementFiles &TUFiles, 67 clang::DiagnosticsEngine &Diagnostics) = delete; 68 69 template <> 70 std::error_code collectReplacementsFromDirectory( 71 const llvm::StringRef Directory, TUReplacements &TUs, 72 TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics); 73 74 template <> 75 std::error_code collectReplacementsFromDirectory( 76 const llvm::StringRef Directory, TUDiagnostics &TUs, 77 TUReplacementFiles &TUFiles, clang::DiagnosticsEngine &Diagnostics); 78 79 /// Deduplicate, check for conflicts, and extract all Replacements stored 80 /// in \c TUs. Conflicting replacements are skipped. 81 /// 82 /// \post For all (key,value) in FileChanges, value[i].getOffset() <= 83 /// value[i+1].getOffset(). 84 /// 85 /// \param[in] TUs Collection of TranslationUnitReplacements or 86 /// TranslationUnitDiagnostics to merge, deduplicate, and test for conflicts. 87 /// \param[out] FileChanges Container grouping all changes by the 88 /// file they target. Only non conflicting replacements are kept into 89 /// FileChanges. 90 /// \param[in] SM SourceManager required for conflict reporting. 91 /// 92 /// \returns \parblock 93 /// \li true If all changes were converted successfully. 94 /// \li false If there were conflicts. 95 bool mergeAndDeduplicate(const TUReplacements &TUs, const TUDiagnostics &TUDs, 96 FileToChangesMap &FileChanges, 97 clang::SourceManager &SM, 98 bool IgnoreInsertConflict = false); 99 100 /// Apply \c AtomicChange on File and rewrite it. 101 /// 102 /// \param[in] File Path of the file where to apply AtomicChange. 103 /// \param[in] Changes to apply. 104 /// \param[in] Spec For code cleanup and formatting. 105 /// \param[in] Diagnostics DiagnosticsEngine used for error output. 106 /// 107 /// \returns The changed code if all changes are applied successfully; 108 /// otherwise, an llvm::Error carrying llvm::StringError or an error_code. 109 llvm::Expected<std::string> 110 applyChanges(StringRef File, const std::vector<tooling::AtomicChange> &Changes, 111 const tooling::ApplyChangesSpec &Spec, 112 DiagnosticsEngine &Diagnostics); 113 114 /// Delete the replacement files. 115 /// 116 /// \param[in] Files Replacement files to delete. 117 /// \param[in] Diagnostics DiagnosticsEngine used for error output. 118 /// 119 /// \returns \parblock 120 /// \li true If all files have been deleted successfully. 121 /// \li false If at least one or more failures occur when deleting 122 /// files. 123 bool deleteReplacementFiles(const TUReplacementFiles &Files, 124 clang::DiagnosticsEngine &Diagnostics); 125 126 } // end namespace replace 127 } // end namespace clang 128 129 #endif // LLVM_CLANG_APPLYREPLACEMENTS_H 130