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