1 //===--- Rename.h - Symbol-rename refactorings -------------------*- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_RENAME_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_RENAME_H 11 12 #include "Protocol.h" 13 #include "SourceCode.h" 14 #include "support/Path.h" 15 #include "clang/Basic/LangOptions.h" 16 #include "clang/Tooling/Core/Replacement.h" 17 #include "llvm/Support/Error.h" 18 19 namespace clang { 20 namespace clangd { 21 class ParsedAST; 22 class SymbolIndex; 23 24 /// Gets dirty buffer for a given file \p AbsPath. 25 /// Returns None if there is no dirty buffer for the given file. 26 using DirtyBufferGetter = 27 llvm::function_ref<llvm::Optional<std::string>(PathRef AbsPath)>; 28 29 struct RenameOptions { 30 /// If true, enable cross-file rename; otherwise, only allows to rename a 31 /// symbol that's only used in the current file. 32 bool AllowCrossFile = false; 33 /// The maximum number of affected files (0 means no limit), only meaningful 34 /// when AllowCrossFile = true. 35 /// If the actual number exceeds the limit, rename is forbidden. 36 size_t LimitFiles = 50; 37 /// If true, format the rename edits, only meaningful in ClangdServer layer. 38 bool WantFormat = false; 39 }; 40 41 struct RenameInputs { 42 Position Pos; // the position triggering the rename 43 llvm::StringRef NewName; 44 45 ParsedAST &AST; 46 llvm::StringRef MainFilePath; 47 48 const SymbolIndex *Index = nullptr; 49 50 RenameOptions Opts = {}; 51 // When set, used by the rename to get file content for all rename-related 52 // files. 53 // If there is no corresponding dirty buffer, we will use the file content 54 // from disk. 55 DirtyBufferGetter GetDirtyBuffer = nullptr; 56 }; 57 58 struct RenameResult { 59 // The range of the symbol that the user can attempt to rename. 60 Range Target; 61 // Rename occurrences for the current main file. 62 std::vector<Range> LocalChanges; 63 // Complete edits for the rename, including LocalChanges. 64 // If the full set of changes is unknown, this field is empty. 65 FileEdits GlobalChanges; 66 }; 67 68 /// Renames all occurrences of the symbol. The result edits are unformatted. 69 /// If AllowCrossFile is false, returns an error if rename a symbol that's used 70 /// in another file (per the index). 71 llvm::Expected<RenameResult> rename(const RenameInputs &RInputs); 72 73 /// Generates rename edits that replaces all given occurrences with the 74 /// NewName. 75 /// Exposed for testing only. 76 /// REQUIRED: Occurrences is sorted and doesn't have duplicated ranges. 77 llvm::Expected<Edit> buildRenameEdit(llvm::StringRef AbsFilePath, 78 llvm::StringRef InitialCode, 79 std::vector<Range> Occurrences, 80 llvm::StringRef NewName); 81 82 /// Adjusts indexed occurrences to match the current state of the file. 83 /// 84 /// The Index is not always up to date. Blindly editing at the locations 85 /// reported by the index may mangle the code in such cases. 86 /// This function determines whether the indexed occurrences can be applied to 87 /// this file, and heuristically repairs the occurrences if necessary. 88 /// 89 /// The API assumes that Indexed contains only named occurrences (each 90 /// occurrence has the same length). 91 /// REQUIRED: Indexed is sorted. 92 llvm::Optional<std::vector<Range>> 93 adjustRenameRanges(llvm::StringRef DraftCode, llvm::StringRef Identifier, 94 std::vector<Range> Indexed, const LangOptions &LangOpts); 95 96 /// Calculates the lexed occurrences that the given indexed occurrences map to. 97 /// Returns None if we don't find a mapping. 98 /// 99 /// Exposed for testing only. 100 /// 101 /// REQUIRED: Indexed and Lexed are sorted. 102 llvm::Optional<std::vector<Range>> getMappedRanges(ArrayRef<Range> Indexed, 103 ArrayRef<Range> Lexed); 104 /// Evaluates how good the mapped result is. 0 indicates a perfect match. 105 /// 106 /// Exposed for testing only. 107 /// 108 /// REQUIRED: Indexed and Lexed are sorted, Indexed and MappedIndex have the 109 /// same size. 110 size_t renameRangeAdjustmentCost(ArrayRef<Range> Indexed, ArrayRef<Range> Lexed, 111 ArrayRef<size_t> MappedIndex); 112 113 } // namespace clangd 114 } // namespace clang 115 116 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_REFACTOR_RENAME_H 117