1558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===//
2558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//
3558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//                     The LLVM Compiler Infrastructure
4558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//
5558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor// This file is distributed under the University of Illinois Open Source
6558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor// License. See LICENSE.TXT for details.
7558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//
8558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//===----------------------------------------------------------------------===//
9558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//
10558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor// This is a diagnostic client adaptor that performs rewrites as
11558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor// suggested by code modification hints attached to diagnostics. It
12558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor// then forwards any diagnostics to the adapted diagnostic client.
13558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//
14558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor//===----------------------------------------------------------------------===//
15176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
16176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
17558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
18558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor#include "clang/Basic/Diagnostic.h"
19d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky#include "clang/Basic/SourceLocation.h"
2030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditedSource.h"
2130a2e16f6c27f888dd11eba6bbbae1e980078fcbChandler Carruth#include "clang/Rewrite/Core/Rewriter.h"
22558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
23558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregornamespace clang {
24558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
25558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregorclass SourceManager;
2626df2f09587ad6978ac8e357ca46b2731d591cc4Douglas Gregorclass FileEntry;
2726df2f09587ad6978ac8e357ca46b2731d591cc4Douglas Gregor
281450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewyckyclass FixItOptions {
29ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewyckypublic:
3061d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  FixItOptions() : FixWhatYouCan(false),
3161d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis                   FixOnlyWarnings(false), Silent(false) { }
3261d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis
331450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky  virtual ~FixItOptions();
34ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky
35ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky  /// \brief This file is about to be rewritten. Return the name of the file
36ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky  /// that is okay to write to.
37c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  ///
38c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  /// \param fd out parameter for file descriptor. After the call it may be set
39c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  /// to an open file descriptor for the returned filename, or it will be -1
40c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  /// otherwise.
41c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  ///
42c8af9107fd1eb014d9124b753c38c4d06fa219f4Argyrios Kyrtzidis  virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;
431450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky
441450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky  /// \brief Whether to abort fixing a file when not all errors could be fixed.
451450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky  bool FixWhatYouCan;
4661d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis
4761d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  /// \brief Whether to only fix warnings and not errors.
4861d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  bool FixOnlyWarnings;
4961d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis
5061d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  /// \brief If true, only pass the diagnostic to the actual diagnostic consumer
5161d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  /// if it is an error or a fixit was applied as part of the diagnostic.
5261d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  /// It basically silences warnings without accompanying fixits.
5361d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  bool Silent;
5426df2f09587ad6978ac8e357ca46b2731d591cc4Douglas Gregor};
55558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
5678ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikieclass FixItRewriter : public DiagnosticConsumer {
57de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor  /// \brief The diagnostics machinery.
58d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  DiagnosticsEngine &Diags;
59558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  edit::EditedSource Editor;
6130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
62558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// \brief The rewriter used to perform the various code
63558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// modifications.
64de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor  Rewriter Rewrite;
65de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor
66de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor  /// \brief The diagnostic client that performs the actual formatting
67de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor  /// of error messages.
6878ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *Client;
69176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  std::unique_ptr<DiagnosticConsumer> Owner;
70558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
71ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky  /// \brief Turn an input path into an output path. NULL implies overwriting
72ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky  /// the original.
731450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky  FixItOptions *FixItOpts;
74ba5f6eced29937e4e4851a2c0980744768413d66Nick Lewycky
75558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// \brief The number of rewriter failures.
76558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  unsigned NumFailures;
77558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
7861d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  /// \brief Whether the previous diagnostic was not passed to the consumer.
7961d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  bool PrevDiagSilenced;
8061d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis
81558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregorpublic:
82d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  typedef Rewriter::buffer_iterator iterator;
83d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky
84558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// \brief Initialize a new fix-it rewriter.
85d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
861450f265fcc84a7ca64dd9f3b8d4492c5bd55e23Nick Lewycky                const LangOptions &LangOpts, FixItOptions *FixItOpts);
87558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
88558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// \brief Destroy the fix-it rewriter.
8933337ca4d89605025818daf83390ab4271d598d9Pirama Arumuga Nainar  ~FixItRewriter() override;
90558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
91d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  /// \brief Check whether there are modifications for a given file.
92d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  bool IsModified(FileID ID) const {
936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    return Rewrite.getRewriteBufferFor(ID) != nullptr;
94d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  }
95d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky
96d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  // Iteration over files with changes.
97d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  iterator buffer_begin() { return Rewrite.buffer_begin(); }
98d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  iterator buffer_end() { return Rewrite.buffer_end(); }
99d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky
100d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  /// \brief Write a single modified source file.
101d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  ///
102d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  /// \returns true if there was an error, false otherwise.
1038cc488fefb2fb04bc8d5398da29f0182f97934cfChris Lattner  bool WriteFixedFile(FileID ID, raw_ostream &OS);
104d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky
105d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  /// \brief Write the modified source files.
106558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  ///
107558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// \returns true if there was an error, false otherwise.
10861d679ab2831b161c857cf3f974312fbd4ef1efdArgyrios Kyrtzidis  bool WriteFixedFiles(
1096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines     std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr);
110558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
111558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// IncludeInDiagnosticCounts - This method (whose default implementation
112d4a97a18ea3cda3ba095e7c0c6708e7a39cf31dbNick Lewycky  /// returns true) indicates whether the diagnostics handled by this
11378ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  /// DiagnosticConsumer should be included in the number of diagnostics
114d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  /// reported by DiagnosticsEngine.
115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool IncludeInDiagnosticCounts() const override;
116558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
117558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
118558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor  /// capturing it to a log as needed.
119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                        const Diagnostic &Info) override;
121558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
122de4bf6a63219c5b9d3bce1fed3dfe075568098a0Douglas Gregor  /// \brief Emit a diagnostic via the adapted diagnostic client.
12333e4e70c8c0a17e0ccb7465d96556b077a68ecb1Argyrios Kyrtzidis  void Diag(SourceLocation Loc, unsigned DiagID);
124558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor};
125558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
126558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor}
127558cb56caf8906e0adbe643e3febbef0b7af1b9fDouglas Gregor
128176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#endif
129