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