Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
 
17
#include "clang/Basic/SourceManager.h"
18
#include "clang/Format/Format.h"
19
#include "clang/Tooling/Core/Replacement.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
 
55
  AtomicChange &operator=(AtomicChange &&) = default;
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
 
121
  llvm::ArrayRef<std::string> getInsertedHeaders() const {
122
    return InsertedHeaders;
123
  }
124
 
125
  llvm::ArrayRef<std::string> getRemovedHeaders() const {
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,
137
               clang::tooling::Replacements Replaces);
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.
157
struct ApplyChangesSpec {
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
 
163
  format::FormatStyle Style = format::getNoStyle();
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`.
169
  enum FormatOption { kAll, kNone, kViolations };
170
 
171
  FormatOption Format = kNone;
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).
184
llvm::Expected<std::string>
185
applyAtomicChanges(llvm::StringRef FilePath, llvm::StringRef Code,
186
                   llvm::ArrayRef<AtomicChange> Changes,
187
                   const ApplyChangesSpec &Spec);
188
 
189
} // end namespace tooling
190
} // end namespace clang
191
 
192
#endif // LLVM_CLANG_TOOLING_REFACTORING_ATOMICCHANGE_H