summaryrefslogtreecommitdiffstats
path: root/include/clang/Rewrite/Frontend/FixItRewriter.h
blob: f514f3628a559bcf598d2c000d0de7d0b6aef045 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//===- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is a diagnostic client adaptor that performs rewrites as
// suggested by code modification hints attached to diagnostics. It
// then forwards any diagnostics to the adapted diagnostic client.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H
#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Edit/EditedSource.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>

namespace clang {

class LangOptions;
class SourceManager;

class FixItOptions {
public:
  FixItOptions() = default;
  virtual ~FixItOptions();

  /// This file is about to be rewritten. Return the name of the file
  /// that is okay to write to.
  ///
  /// \param fd out parameter for file descriptor. After the call it may be set
  /// to an open file descriptor for the returned filename, or it will be -1
  /// otherwise.
  virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0;

  /// True if files should be updated in place. RewriteFilename is only called
  /// if this is false.
  bool InPlace = false;

  /// Whether to abort fixing a file when not all errors could be fixed.
  bool FixWhatYouCan = false;

  /// Whether to only fix warnings and not errors.
  bool FixOnlyWarnings = false;

  /// If true, only pass the diagnostic to the actual diagnostic consumer
  /// if it is an error or a fixit was applied as part of the diagnostic.
  /// It basically silences warnings without accompanying fixits.
  bool Silent = false;
};

class FixItRewriter : public DiagnosticConsumer {
  /// The diagnostics machinery.
  DiagnosticsEngine &Diags;

  edit::EditedSource Editor;

  /// The rewriter used to perform the various code
  /// modifications.
  Rewriter Rewrite;

  /// The diagnostic client that performs the actual formatting
  /// of error messages.
  DiagnosticConsumer *Client;
  std::unique_ptr<DiagnosticConsumer> Owner;

  /// Turn an input path into an output path. NULL implies overwriting
  /// the original.
  FixItOptions *FixItOpts;

  /// The number of rewriter failures.
  unsigned NumFailures = 0;

  /// Whether the previous diagnostic was not passed to the consumer.
  bool PrevDiagSilenced = false;

public:
  /// Initialize a new fix-it rewriter.
  FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
                const LangOptions &LangOpts, FixItOptions *FixItOpts);

  /// Destroy the fix-it rewriter.
  ~FixItRewriter() override;

  /// Check whether there are modifications for a given file.
  bool IsModified(FileID ID) const {
    return Rewrite.getRewriteBufferFor(ID) != nullptr;
  }

  using iterator = Rewriter::buffer_iterator;

  // Iteration over files with changes.
  iterator buffer_begin() { return Rewrite.buffer_begin(); }
  iterator buffer_end() { return Rewrite.buffer_end(); }

  /// Write a single modified source file.
  ///
  /// \returns true if there was an error, false otherwise.
  bool WriteFixedFile(FileID ID, raw_ostream &OS);

  /// Write the modified source files.
  ///
  /// \returns true if there was an error, false otherwise.
  bool WriteFixedFiles(
    std::vector<std::pair<std::string, std::string>> *RewrittenFiles = nullptr);

  /// IncludeInDiagnosticCounts - This method (whose default implementation
  /// returns true) indicates whether the diagnostics handled by this
  /// DiagnosticConsumer should be included in the number of diagnostics
  /// reported by DiagnosticsEngine.
  bool IncludeInDiagnosticCounts() const override;

  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
  /// capturing it to a log as needed.
  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                        const Diagnostic &Info) override;

  /// Emit a diagnostic via the adapted diagnostic client.
  void Diag(SourceLocation Loc, unsigned DiagID);
};

} // namespace clang

#endif // LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H