clang 20.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
24namespace clang {
25namespace 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.
38public:
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
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
131private:
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
154using 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).
185applyAtomicChanges(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:84
StringRef Text
Definition: Format.cpp:3033
Various functions to configurably format source code.
SourceLocation Loc
Definition: SemaObjC.cpp:759
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
AtomicChange & operator=(AtomicChange &&)=default
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.
llvm::Error insert(const SourceManager &SM, SourceLocation Loc, llvm::StringRef Text, bool InsertAfter=true)
Adds a replacement that inserts Text at Loc.
const std::string & getFilePath() const
Returns the path of the file containing this atomic change.
Definition: AtomicChange.h:71
void setError(llvm::StringRef Error)
If this change could not be created successfully, e.g.
Definition: AtomicChange.h:77
AtomicChange & operator=(const AtomicChange &)=default
static AtomicChange convertFromYAML(llvm::StringRef YAMLContent)
Converts a YAML-encoded automic change to AtomicChange.
llvm::ArrayRef< std::string > getRemovedHeaders() const
Definition: AtomicChange.h:125
bool hasError() const
Returns whether an error has been set on this list.
Definition: AtomicChange.h:80
const std::string & getError() const
Returns the error message or an empty string if it does not exist.
Definition: AtomicChange.h:83
Replacements & getReplacements()
Definition: AtomicChange.h:119
AtomicChange(const AtomicChange &)=default
bool operator==(const AtomicChange &Other) const
const llvm::Any & getMetadata() const
Definition: AtomicChange.h:129
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.
const Replacements & getReplacements() const
Returns a const reference to existing replacements.
Definition: AtomicChange.h:117
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
llvm::ArrayRef< std::string > getInsertedHeaders() const
Definition: AtomicChange.h:121
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:1980
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.
@ Other
Other implicit parameter.
The FormatStyle is used to configure the formatting to follow specific guidelines.
Definition: Format.h:55