16
16
#include " clang/Tooling/Tooling.h"
17
17
#include " llvm/ADT/STLFunctionalExtras.h"
18
18
#include " llvm/ADT/SmallVector.h"
19
+ #include " llvm/ADT/StringMap.h"
19
20
#include " llvm/ADT/StringRef.h"
20
21
#include " llvm/Support/CommandLine.h"
21
22
#include " llvm/Support/FormatVariadic.h"
22
- #include " llvm/Support/MemoryBuffer.h"
23
23
#include " llvm/Support/Regex.h"
24
24
#include " llvm/Support/Signals.h"
25
25
#include " llvm/Support/raw_ostream.h"
@@ -110,14 +110,16 @@ format::FormatStyle getStyle(llvm::StringRef Filename) {
110
110
111
111
class Action : public clang ::ASTFrontendAction {
112
112
public:
113
- Action (llvm::function_ref<bool (llvm::StringRef)> HeaderFilter)
114
- : HeaderFilter(HeaderFilter){};
113
+ Action (llvm::function_ref<bool (llvm::StringRef)> HeaderFilter,
114
+ llvm::StringMap<std::string> &EditedFiles)
115
+ : HeaderFilter(HeaderFilter), EditedFiles(EditedFiles) {}
115
116
116
117
private:
117
118
RecordedAST AST;
118
119
RecordedPP PP;
119
120
PragmaIncludes PI;
120
121
llvm::function_ref<bool (llvm::StringRef)> HeaderFilter;
122
+ llvm::StringMap<std::string> &EditedFiles;
121
123
122
124
bool BeginInvocation (CompilerInstance &CI) override {
123
125
// We only perform include-cleaner analysis. So we disable diagnostics that
@@ -181,17 +183,8 @@ class Action : public clang::ASTFrontendAction {
181
183
}
182
184
}
183
185
184
- if (Edit && (!Results.Missing .empty () || !Results.Unused .empty ())) {
185
- if (auto Err = llvm::writeToOutput (
186
- Path, [&](llvm::raw_ostream &OS) -> llvm::Error {
187
- OS << Final;
188
- return llvm::Error::success ();
189
- })) {
190
- llvm::errs () << " Failed to apply edits to " << Path << " : "
191
- << toString (std::move (Err)) << " \n " ;
192
- ++Errors;
193
- }
194
- }
186
+ if (!Results.Missing .empty () || !Results.Unused .empty ())
187
+ EditedFiles.try_emplace (Path, Final);
195
188
}
196
189
197
190
void writeHTML () {
@@ -215,11 +208,17 @@ class ActionFactory : public tooling::FrontendActionFactory {
215
208
: HeaderFilter(HeaderFilter) {}
216
209
217
210
std::unique_ptr<clang::FrontendAction> create () override {
218
- return std::make_unique<Action>(HeaderFilter);
211
+ return std::make_unique<Action>(HeaderFilter, EditedFiles);
212
+ }
213
+
214
+ const llvm::StringMap<std::string> &editedFiles () const {
215
+ return EditedFiles;
219
216
}
220
217
221
218
private:
222
219
llvm::function_ref<bool (llvm::StringRef)> HeaderFilter;
220
+ // Map from file name to final code with the include edits applied.
221
+ llvm::StringMap<std::string> EditedFiles;
223
222
};
224
223
225
224
std::function<bool (llvm::StringRef)> headerFilter () {
@@ -274,21 +273,26 @@ int main(int argc, const char **argv) {
274
273
275
274
clang::tooling::ClangTool Tool (OptionsParser->getCompilations (),
276
275
OptionsParser->getSourcePathList ());
277
- std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
278
- for (const auto &File : OptionsParser->getSourcePathList ()) {
279
- auto Content = llvm::MemoryBuffer::getFile (File);
280
- if (!Content) {
281
- llvm::errs () << " Error: can't read file '" << File
282
- << " ': " << Content.getError ().message () << " \n " ;
283
- return 1 ;
284
- }
285
- Buffers.push_back (std::move (Content.get ()));
286
- Tool.mapVirtualFile (File, Buffers.back ()->getBuffer ());
287
- }
288
276
289
277
auto HeaderFilter = headerFilter ();
290
278
if (!HeaderFilter)
291
279
return 1 ; // error already reported.
292
280
ActionFactory Factory (HeaderFilter);
293
- return Tool.run (&Factory) || Errors != 0 ;
281
+ auto ErrorCode = Tool.run (&Factory);
282
+ if (Edit) {
283
+ for (const auto &NameAndContent : Factory.editedFiles ()) {
284
+ llvm::StringRef FileName = NameAndContent.first ();
285
+ const std::string &FinalCode = NameAndContent.second ;
286
+ if (auto Err = llvm::writeToOutput (
287
+ FileName, [&](llvm::raw_ostream &OS) -> llvm::Error {
288
+ OS << FinalCode;
289
+ return llvm::Error::success ();
290
+ })) {
291
+ llvm::errs () << " Failed to apply edits to " << FileName << " : "
292
+ << toString (std::move (Err)) << " \n " ;
293
+ ++Errors;
294
+ }
295
+ }
296
+ }
297
+ return ErrorCode || Errors != 0 ;
294
298
}
0 commit comments