1 //===---------- IncludeInserter.h - clang-tidy ----------------------------===//
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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDEINSERTER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDEINSERTER_H
11 
12 #include "IncludeSorter.h"
13 #include "clang/Basic/Diagnostic.h"
14 #include "llvm/ADT/StringSet.h"
15 #include <memory>
16 
17 namespace clang {
18 class Preprocessor;
19 namespace tidy {
20 namespace utils {
21 
22 /// Produces fixes to insert specified includes to source files, if not
23 /// yet present.
24 ///
25 /// ``IncludeInserter`` can be used in clang-tidy checks in the following way:
26 /// \code
27 /// #include "../ClangTidyCheck.h"
28 /// #include "../utils/IncludeInserter.h"
29 ///
30 /// namespace clang {
31 /// namespace tidy {
32 ///
33 /// class MyCheck : public ClangTidyCheck {
34 ///  public:
35 ///   void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
36 ///                            Preprocessor *ModuleExpanderPP) override {
37 ///     Inserter.registerPreprocessor(PP);
38 ///   }
39 ///
40 ///   void registerMatchers(ast_matchers::MatchFinder* Finder) override { ... }
41 ///
42 ///   void check(
43 ///       const ast_matchers::MatchFinder::MatchResult& Result) override {
44 ///     ...
45 ///     Inserter.createMainFileIncludeInsertion("path/to/Header.h");
46 ///     ...
47 ///   }
48 ///
49 ///  private:
50 ///   utils::IncludeInserter Inserter{utils::IncludeSorter::IS_Google};
51 /// };
52 /// } // namespace tidy
53 /// } // namespace clang
54 /// \endcode
55 class IncludeInserter {
56 public:
57   /// Initializes the IncludeInserter using the IncludeStyle \p Style.
58   /// In most cases the \p Style will be retrieved from the ClangTidyOptions
59   /// using \code
60   ///   Options.getLocalOrGlobal("IncludeStyle", <DefaultStyle>)
61   /// \endcode
62   explicit IncludeInserter(IncludeSorter::IncludeStyle Style);
63 
64   /// Registers this with the Preprocessor \p PP, must be called before this
65   /// class is used.
66   void registerPreprocessor(Preprocessor *PP);
67 
68   /// Creates a \p Header inclusion directive fixit in the File \p FileID.
69   /// When \p Header is enclosed in angle brackets, uses angle brackets in the
70   /// inclusion directive, otherwise uses quotes.
71   /// Returns ``llvm::None`` on error or if the inclusion directive already
72   /// exists.
73   llvm::Optional<FixItHint> createIncludeInsertion(FileID FileID,
74                                                    llvm::StringRef Header);
75 
76   /// Creates a \p Header inclusion directive fixit in the main file.
77   /// When \p Header is enclosed in angle brackets, uses angle brackets in the
78   /// inclusion directive, otherwise uses quotes.
79   /// Returns ``llvm::None`` on error or if the inclusion directive already
80   /// exists.
81   llvm::Optional<FixItHint>
82   createMainFileIncludeInsertion(llvm::StringRef Header);
83 
getStyle()84   IncludeSorter::IncludeStyle getStyle() const { return Style; }
85 
86 private:
87   void addInclude(StringRef FileName, bool IsAngled,
88                   SourceLocation HashLocation, SourceLocation EndLocation);
89 
90   IncludeSorter &getOrCreate(FileID FileID);
91 
92   llvm::DenseMap<FileID, std::unique_ptr<IncludeSorter>> IncludeSorterByFile;
93   llvm::DenseMap<FileID, llvm::StringSet<>> InsertedHeaders;
94   const SourceManager *SourceMgr{nullptr};
95   const IncludeSorter::IncludeStyle Style;
96   friend class IncludeInserterCallback;
97 };
98 
99 } // namespace utils
100 } // namespace tidy
101 } // namespace clang
102 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDEINSERTER_H
103