clang-tools 17.0.0git
IncludeInserter.cpp
Go to the documentation of this file.
1//===-------- IncludeInserter.cpp - 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#include "IncludeInserter.h"
10#include "clang/Lex/PPCallbacks.h"
11#include "clang/Lex/Preprocessor.h"
12#include "clang/Lex/Token.h"
13#include <optional>
14
15namespace clang::tidy::utils {
16
17class IncludeInserterCallback : public PPCallbacks {
18public:
20 : Inserter(Inserter) {}
21 // Implements PPCallbacks::InclusionDirective(). Records the names and source
22 // locations of the inclusions in the main source file being processed.
23 void InclusionDirective(SourceLocation HashLocation,
24 const Token &IncludeToken, StringRef FileNameRef,
25 bool IsAngled, CharSourceRange FileNameRange,
26 OptionalFileEntryRef /*IncludedFile*/,
27 StringRef /*SearchPath*/, StringRef /*RelativePath*/,
28 const Module * /*ImportedModule*/,
29 SrcMgr::CharacteristicKind /*FileType*/) override {
30 Inserter->addInclude(FileNameRef, IsAngled, HashLocation,
31 IncludeToken.getEndLoc());
32 }
33
34private:
35 IncludeInserter *Inserter;
36};
37
39 bool SelfContainedDiags)
40 : Style(Style), SelfContainedDiags(SelfContainedDiags) {}
41
43 assert(PP && "PP shouldn't be null");
44 SourceMgr = &PP->getSourceManager();
45
46 // If this gets registered multiple times, clear the maps
47 if (!IncludeSorterByFile.empty())
48 IncludeSorterByFile.clear();
49 if (!InsertedHeaders.empty())
50 InsertedHeaders.clear();
51 PP->addPPCallbacks(std::make_unique<IncludeInserterCallback>(this));
52}
53
54IncludeSorter &IncludeInserter::getOrCreate(FileID FileID) {
55 assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "
56 "registerPreprocessor()?");
57 // std::unique_ptr is cheap to construct, so force a construction now to save
58 // the lookup needed if we were to insert into the map.
59 std::unique_ptr<IncludeSorter> &Entry = IncludeSorterByFile[FileID];
60 if (!Entry) {
61 // If it wasn't found, Entry will be default constructed to nullptr.
62 Entry = std::make_unique<IncludeSorter>(
63 SourceMgr, FileID,
64 SourceMgr->getFilename(SourceMgr->getLocForStartOfFile(FileID)), Style);
65 }
66 return *Entry;
67}
68
69std::optional<FixItHint>
70IncludeInserter::createIncludeInsertion(FileID FileID, llvm::StringRef Header) {
71 bool IsAngled = Header.consume_front("<");
72 if (IsAngled != Header.consume_back(">"))
73 return std::nullopt;
74 // We assume the same Header will never be included both angled and not
75 // angled.
76 // In self contained diags mode we don't track what headers we have already
77 // inserted.
78 if (!SelfContainedDiags && !InsertedHeaders[FileID].insert(Header).second)
79 return std::nullopt;
80
81 return getOrCreate(FileID).createIncludeInsertion(Header, IsAngled);
82}
83
84std::optional<FixItHint>
86 assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "
87 "registerPreprocessor()?");
88 return createIncludeInsertion(SourceMgr->getMainFileID(), Header);
89}
90
91void IncludeInserter::addInclude(StringRef FileName, bool IsAngled,
92 SourceLocation HashLocation,
93 SourceLocation EndLocation) {
94 assert(SourceMgr && "SourceMgr shouldn't be null; did you remember to call "
95 "registerPreprocessor()?");
96 FileID FileID = SourceMgr->getFileID(HashLocation);
97 getOrCreate(FileID).addInclude(FileName, IsAngled, HashLocation, EndLocation);
98}
99
100} // namespace clang::tidy::utils
bool IsAngled
true if this was an include with angle brackets
StringRef FileName
void InclusionDirective(SourceLocation HashLocation, const Token &IncludeToken, StringRef FileNameRef, bool IsAngled, CharSourceRange FileNameRange, OptionalFileEntryRef, StringRef, StringRef, const Module *, SrcMgr::CharacteristicKind) override
IncludeInserterCallback(IncludeInserter *Inserter)
Produces fixes to insert specified includes to source files, if not yet present.
IncludeInserter(IncludeSorter::IncludeStyle Style, bool SelfContainedDiags)
Initializes the IncludeInserter using the IncludeStyle Style.
void registerPreprocessor(Preprocessor *PP)
Registers this with the Preprocessor PP, must be called before this class is used.
std::optional< FixItHint > createIncludeInsertion(FileID FileID, llvm::StringRef Header)
Creates a Header inclusion directive fixit in the File FileID.
std::optional< FixItHint > createMainFileIncludeInsertion(llvm::StringRef Header)
Creates a Header inclusion directive fixit in the main file.
Class used by IncludeInserterCallback to record the names of the inclusions in a given source file be...
Definition: IncludeSorter.h:23
void addInclude(StringRef FileName, bool IsAngled, SourceLocation HashLocation, SourceLocation EndLocation)
Adds the given include directive to the sorter.
IncludeStyle
Supported include styles.
Definition: IncludeSorter.h:26
std::optional< FixItHint > createIncludeInsertion(StringRef FileName, bool IsAngled)
Creates a quoted inclusion directive in the right sort order.