clang  19.0.0git
AtomicChange.h
Go to the documentation of this file.
1 //===--- AtomicChange.h - AtomicChange class --------------------*- 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 // This file defines AtomicChange which is used to create a set of source
10 // changes, e.g. replacements and header insertions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
15 #define LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
16 
18 #include "clang/Format/Format.h"
20 #include "llvm/ADT/Any.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Error.h"
23 
24 namespace clang {
25 namespace tooling {
26 
27 /// An atomic change is used to create and group a set of source edits,
28 /// e.g. replacements or header insertions. Edits in an AtomicChange should be
29 /// related, e.g. replacements for the same type reference and the corresponding
30 /// header insertion/deletion.
31 ///
32 /// An AtomicChange is uniquely identified by a key and will either be fully
33 /// applied or not applied at all.
34 ///
35 /// Calling setError on an AtomicChange stores the error message and marks it as
36 /// bad, i.e. none of its source edits will be applied.
37 class AtomicChange {
38 public:
39  /// Creates an atomic change around \p KeyPosition with the key being a
40  /// concatenation of the file name and the offset of \p KeyPosition.
41  /// \p KeyPosition should be the location of the key syntactical element that
42  /// is being changed, e.g. the call to a refactored method.
43  AtomicChange(const SourceManager &SM, SourceLocation KeyPosition);
44 
45  AtomicChange(const SourceManager &SM, SourceLocation KeyPosition,
46  llvm::Any Metadata);
47 
48  /// Creates an atomic change for \p FilePath with a customized key.
49  AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
50  : Key(Key), FilePath(FilePath) {}
51 
52  AtomicChange(AtomicChange &&) = default;
53  AtomicChange(const AtomicChange &) = default;
54 
56  AtomicChange &operator=(const AtomicChange &) = default;
57 
58  bool operator==(const AtomicChange &Other) const;
59 
60  /// Returns the atomic change as a YAML string.
61  std::string toYAMLString();
62 
63  /// Converts a YAML-encoded automic change to AtomicChange.
64  static AtomicChange convertFromYAML(llvm::StringRef YAMLContent);
65 
66  /// Returns the key of this change, which is a concatenation of the
67  /// file name and offset of the key position.
68  const std::string &getKey() const { return Key; }
69 
70  /// Returns the path of the file containing this atomic change.
71  const std::string &getFilePath() const { return FilePath; }
72 
73  /// If this change could not be created successfully, e.g. because of
74  /// conflicts among replacements, use this to set an error description.
75  /// Thereby, places that cannot be fixed automatically can be gathered when
76  /// applying changes.
77  void setError(llvm::StringRef Error) { this->Error = std::string(Error); }
78 
79  /// Returns whether an error has been set on this list.
80  bool hasError() const { return !Error.empty(); }
81 
82  /// Returns the error message or an empty string if it does not exist.
83  const std::string &getError() const { return Error; }
84 
85  /// Adds a replacement that replaces the given Range with
86  /// ReplacementText.
87  /// \returns An llvm::Error carrying ReplacementError on error.
88  llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range,
89  llvm::StringRef ReplacementText);
90 
91  /// Adds a replacement that replaces range [Loc, Loc+Length) with
92  /// \p Text.
93  /// \returns An llvm::Error carrying ReplacementError on error.
94  llvm::Error replace(const SourceManager &SM, SourceLocation Loc,
95  unsigned Length, llvm::StringRef Text);
96 
97  /// Adds a replacement that inserts \p Text at \p Loc. If this
98  /// insertion conflicts with an existing insertion (at the same position),
99  /// this will be inserted before/after the existing insertion depending on
100  /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they
101  /// do not want conflict resolving by default. If the conflicting replacement
102  /// is not an insertion, an error is returned.
103  ///
104  /// \returns An llvm::Error carrying ReplacementError on error.
105  llvm::Error insert(const SourceManager &SM, SourceLocation Loc,
106  llvm::StringRef Text, bool InsertAfter = true);
107 
108  /// Adds a header into the file that contains the key position.
109  /// Header can be in angle brackets or double quotation marks. By default
110  /// (header is not quoted), header will be surrounded with double quotes.
111  void addHeader(llvm::StringRef Header);
112 
113  /// Removes a header from the file that contains the key position.
114  void removeHeader(llvm::StringRef Header);
115 
116  /// Returns a const reference to existing replacements.
117  const Replacements &getReplacements() const { return Replaces; }
118 
119  Replacements &getReplacements() { return Replaces; }
120 
122  return InsertedHeaders;
123  }
124 
126  return RemovedHeaders;
127  }
128 
129  const llvm::Any &getMetadata() const { return Metadata; }
130 
131 private:
132  AtomicChange() {}
133 
134  AtomicChange(std::string Key, std::string FilePath, std::string Error,
135  std::vector<std::string> InsertedHeaders,
136  std::vector<std::string> RemovedHeaders,
138 
139  // This uniquely identifies an AtomicChange.
140  std::string Key;
141  std::string FilePath;
142  std::string Error;
143  std::vector<std::string> InsertedHeaders;
144  std::vector<std::string> RemovedHeaders;
145  tooling::Replacements Replaces;
146 
147  // This field stores metadata which is ignored for the purposes of applying
148  // edits to source, but may be useful for other consumers of AtomicChanges. In
149  // particular, consumers can use this to direct how they want to consume each
150  // edit.
151  llvm::Any Metadata;
152 };
153 
154 using AtomicChanges = std::vector<AtomicChange>;
155 
156 // Defines specs for applying changes.
158  // If true, cleans up redundant/erroneous code around changed code with
159  // clang-format's cleanup functionality, e.g. redundant commas around deleted
160  // parameter or empty namespaces introduced by deletions.
161  bool Cleanup = true;
162 
164 
165  // Options for selectively formatting changes with clang-format:
166  // kAll: Format all changed lines.
167  // kNone: Don't format anything.
168  // kViolations: Format lines exceeding the `ColumnLimit` in `Style`.
170 
172 };
173 
174 /// Applies all AtomicChanges in \p Changes to the \p Code.
175 ///
176 /// This completely ignores the file path in each change and replaces them with
177 /// \p FilePath, i.e. callers are responsible for ensuring all changes are for
178 /// the same file.
179 ///
180 /// \returns The changed code if all changes are applied successfully;
181 /// otherwise, an llvm::Error carrying llvm::StringError is returned (the Error
182 /// message can be converted to string with `llvm::toString()` and the
183 /// error_code should be ignored).
185 applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
187  const ApplyChangesSpec &Spec);
188 
189 } // end namespace tooling
190 } // end namespace clang
191 
192 #endif // LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H
#define SM(sm)
Definition: Cuda.cpp:83
StringRef Text
Definition: Format.cpp:2977
Various functions to configurably format source code.
SourceLocation Loc
Definition: SemaObjC.cpp:755
Defines the SourceManager interface.
Represents a character-granular source range.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
An atomic change is used to create and group a set of source edits, e.g.
Definition: AtomicChange.h:37
void removeHeader(llvm::StringRef Header)
Removes a header from the file that contains the key position.
std::string toYAMLString()
Returns the atomic change as a YAML string.
AtomicChange(AtomicChange &&)=default
void addHeader(llvm::StringRef Header)
Adds a header into the file that contains the key position.
const llvm::Any & getMetadata() const
Definition: AtomicChange.h:129
llvm::Error insert(const SourceManager &SM, SourceLocation Loc, llvm::StringRef Text, bool InsertAfter=true)
Adds a replacement that inserts Text at Loc.
llvm::ArrayRef< std::string > getRemovedHeaders() const
Definition: AtomicChange.h:125
void setError(llvm::StringRef Error)
If this change could not be created successfully, e.g.
Definition: AtomicChange.h:77
static AtomicChange convertFromYAML(llvm::StringRef YAMLContent)
Converts a YAML-encoded automic change to AtomicChange.
AtomicChange & operator=(AtomicChange &&)=default
bool hasError() const
Returns whether an error has been set on this list.
Definition: AtomicChange.h:80
AtomicChange & operator=(const AtomicChange &)=default
const Replacements & getReplacements() const
Returns a const reference to existing replacements.
Definition: AtomicChange.h:117
const std::string & getError() const
Returns the error message or an empty string if it does not exist.
Definition: AtomicChange.h:83
AtomicChange(const AtomicChange &)=default
bool operator==(const AtomicChange &Other) const
AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key)
Creates an atomic change for FilePath with a customized key.
Definition: AtomicChange.h:49
llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range, llvm::StringRef ReplacementText)
Adds a replacement that replaces the given Range with ReplacementText.
Replacements & getReplacements()
Definition: AtomicChange.h:119
llvm::ArrayRef< std::string > getInsertedHeaders() const
Definition: AtomicChange.h:121
const std::string & getKey() const
Returns the key of this change, which is a concatenation of the file name and offset of the key posit...
Definition: AtomicChange.h:68
const std::string & getFilePath() const
Returns the path of the file containing this atomic change.
Definition: AtomicChange.h:71
A source range independent of the SourceManager.
Definition: Replacement.h:44
Maintains a set of replacements that are conflict-free.
Definition: Replacement.h:212
FormatStyle getNoStyle()
Returns style indicating formatting should be not applied at all.
Definition: Format.cpp:1928
std::vector< AtomicChange > AtomicChanges
Definition: AtomicChange.h:154
llvm::Expected< std::string > applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code, llvm::ArrayRef< AtomicChange > Changes, const ApplyChangesSpec &Spec)
Applies all AtomicChanges in Changes to the Code.
The JSON file list parser is used to communicate input to InstallAPI.
The FormatStyle is used to configure the formatting to follow specific guidelines.
Definition: Format.h:55