xref: /openbsd-src/gnu/llvm/clang/include/clang/Rewrite/Frontend/FixItRewriter.h (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick //===- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ------*- C++ -*-===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This is a diagnostic client adaptor that performs rewrites as
10*e5dd7070Spatrick // suggested by code modification hints attached to diagnostics. It
11*e5dd7070Spatrick // then forwards any diagnostics to the adapted diagnostic client.
12*e5dd7070Spatrick //
13*e5dd7070Spatrick //===----------------------------------------------------------------------===//
14*e5dd7070Spatrick 
15*e5dd7070Spatrick #ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
16*e5dd7070Spatrick #define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
17*e5dd7070Spatrick 
18*e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
19*e5dd7070Spatrick #include "clang/Basic/LLVM.h"
20*e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
21*e5dd7070Spatrick #include "clang/Edit/EditedSource.h"
22*e5dd7070Spatrick #include "clang/Rewrite/Core/Rewriter.h"
23*e5dd7070Spatrick #include <memory>
24*e5dd7070Spatrick #include <string>
25*e5dd7070Spatrick #include <utility>
26*e5dd7070Spatrick #include <vector>
27*e5dd7070Spatrick 
28*e5dd7070Spatrick namespace clang {
29*e5dd7070Spatrick 
30*e5dd7070Spatrick class LangOptions;
31*e5dd7070Spatrick class SourceManager;
32*e5dd7070Spatrick 
33*e5dd7070Spatrick class FixItOptions {
34*e5dd7070Spatrick public:
35*e5dd7070Spatrick   FixItOptions() = default;
36*e5dd7070Spatrick   virtual ~FixItOptions();
37*e5dd7070Spatrick 
38*e5dd7070Spatrick   /// This file is about to be rewritten. Return the name of the file
39*e5dd7070Spatrick   /// that is okay to write to.
40*e5dd7070Spatrick   ///
41*e5dd7070Spatrick   /// \param fd out parameter for file descriptor. After the call it may be set
42*e5dd7070Spatrick   /// to an open file descriptor for the returned filename, or it will be -1
43*e5dd7070Spatrick   /// otherwise.
44*e5dd7070Spatrick   virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;
45*e5dd7070Spatrick 
46*e5dd7070Spatrick   /// True if files should be updated in place. RewriteFilename is only called
47*e5dd7070Spatrick   /// if this is false.
48*e5dd7070Spatrick   bool InPlace = false;
49*e5dd7070Spatrick 
50*e5dd7070Spatrick   /// Whether to abort fixing a file when not all errors could be fixed.
51*e5dd7070Spatrick   bool FixWhatYouCan = false;
52*e5dd7070Spatrick 
53*e5dd7070Spatrick   /// Whether to only fix warnings and not errors.
54*e5dd7070Spatrick   bool FixOnlyWarnings = false;
55*e5dd7070Spatrick 
56*e5dd7070Spatrick   /// If true, only pass the diagnostic to the actual diagnostic consumer
57*e5dd7070Spatrick   /// if it is an error or a fixit was applied as part of the diagnostic.
58*e5dd7070Spatrick   /// It basically silences warnings without accompanying fixits.
59*e5dd7070Spatrick   bool Silent = false;
60*e5dd7070Spatrick };
61*e5dd7070Spatrick 
62*e5dd7070Spatrick class FixItRewriter : public DiagnosticConsumer {
63*e5dd7070Spatrick   /// The diagnostics machinery.
64*e5dd7070Spatrick   DiagnosticsEngine &Diags;
65*e5dd7070Spatrick 
66*e5dd7070Spatrick   edit::EditedSource Editor;
67*e5dd7070Spatrick 
68*e5dd7070Spatrick   /// The rewriter used to perform the various code
69*e5dd7070Spatrick   /// modifications.
70*e5dd7070Spatrick   Rewriter Rewrite;
71*e5dd7070Spatrick 
72*e5dd7070Spatrick   /// The diagnostic client that performs the actual formatting
73*e5dd7070Spatrick   /// of error messages.
74*e5dd7070Spatrick   DiagnosticConsumer *Client;
75*e5dd7070Spatrick   std::unique_ptr<DiagnosticConsumer> Owner;
76*e5dd7070Spatrick 
77*e5dd7070Spatrick   /// Turn an input path into an output path. NULL implies overwriting
78*e5dd7070Spatrick   /// the original.
79*e5dd7070Spatrick   FixItOptions *FixItOpts;
80*e5dd7070Spatrick 
81*e5dd7070Spatrick   /// The number of rewriter failures.
82*e5dd7070Spatrick   unsigned NumFailures = 0;
83*e5dd7070Spatrick 
84*e5dd7070Spatrick   /// Whether the previous diagnostic was not passed to the consumer.
85*e5dd7070Spatrick   bool PrevDiagSilenced = false;
86*e5dd7070Spatrick 
87*e5dd7070Spatrick public:
88*e5dd7070Spatrick   /// Initialize a new fix-it rewriter.
89*e5dd7070Spatrick   FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
90*e5dd7070Spatrick                 const LangOptions &LangOpts, FixItOptions *FixItOpts);
91*e5dd7070Spatrick 
92*e5dd7070Spatrick   /// Destroy the fix-it rewriter.
93*e5dd7070Spatrick   ~FixItRewriter() override;
94*e5dd7070Spatrick 
95*e5dd7070Spatrick   /// Check whether there are modifications for a given file.
IsModified(FileID ID)96*e5dd7070Spatrick   bool IsModified(FileID ID) const {
97*e5dd7070Spatrick     return Rewrite.getRewriteBufferFor(ID) != nullptr;
98*e5dd7070Spatrick   }
99*e5dd7070Spatrick 
100*e5dd7070Spatrick   using iterator = Rewriter::buffer_iterator;
101*e5dd7070Spatrick 
102*e5dd7070Spatrick   // Iteration over files with changes.
buffer_begin()103*e5dd7070Spatrick   iterator buffer_begin() { return Rewrite.buffer_begin(); }
buffer_end()104*e5dd7070Spatrick   iterator buffer_end() { return Rewrite.buffer_end(); }
105*e5dd7070Spatrick 
106*e5dd7070Spatrick   /// Write a single modified source file.
107*e5dd7070Spatrick   ///
108*e5dd7070Spatrick   /// \returns true if there was an error, false otherwise.
109*e5dd7070Spatrick   bool WriteFixedFile(FileID ID, raw_ostream &OS);
110*e5dd7070Spatrick 
111*e5dd7070Spatrick   /// Write the modified source files.
112*e5dd7070Spatrick   ///
113*e5dd7070Spatrick   /// \returns true if there was an error, false otherwise.
114*e5dd7070Spatrick   bool WriteFixedFiles(
115*e5dd7070Spatrick     std::vector<std::pair<std::string, std::string>> *RewrittenFiles = nullptr);
116*e5dd7070Spatrick 
117*e5dd7070Spatrick   /// IncludeInDiagnosticCounts - This method (whose default implementation
118*e5dd7070Spatrick   /// returns true) indicates whether the diagnostics handled by this
119*e5dd7070Spatrick   /// DiagnosticConsumer should be included in the number of diagnostics
120*e5dd7070Spatrick   /// reported by DiagnosticsEngine.
121*e5dd7070Spatrick   bool IncludeInDiagnosticCounts() const override;
122*e5dd7070Spatrick 
123*e5dd7070Spatrick   /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
124*e5dd7070Spatrick   /// capturing it to a log as needed.
125*e5dd7070Spatrick   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
126*e5dd7070Spatrick                         const Diagnostic &Info) override;
127*e5dd7070Spatrick 
128*e5dd7070Spatrick   /// Emit a diagnostic via the adapted diagnostic client.
129*e5dd7070Spatrick   void Diag(SourceLocation Loc, unsigned DiagID);
130*e5dd7070Spatrick };
131*e5dd7070Spatrick 
132*e5dd7070Spatrick } // namespace clang
133*e5dd7070Spatrick 
134*e5dd7070Spatrick #endif // LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
135