14 #include "clang/Frontend/CompilerInstance.h" 15 #include "clang/Index/IndexingAction.h" 16 #include "clang/Tooling/Tooling.h" 23 llvm::Optional<std::string> toURI(
const FileEntry *File) {
26 auto AbsolutePath = File->tryGetRealPathName();
27 if (AbsolutePath.empty())
37 IncludeGraphCollector(
const SourceManager &SM,
IncludeGraph &IG)
44 void FileChanged(SourceLocation
Loc, FileChangeReason Reason,
45 SrcMgr::CharacteristicKind FileType,
46 FileID PrevFID)
override {
49 if (Reason != FileChangeReason::EnterFile)
52 const auto FileID = SM.getFileID(Loc);
53 const auto File = SM.getFileEntryForID(FileID);
54 auto URI = toURI(File);
57 auto I = IG.try_emplace(*URI).first;
59 auto &Node = I->getValue();
61 if (Node.URI.data() == I->getKeyData()) {
64 assert(Digest && Node.Digest == *Digest &&
65 "Same file, different digest?");
70 Node.Digest = std::move(*Digest);
71 if (FileID == SM.getMainFileID())
73 Node.URI = I->getKey();
77 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
79 CharSourceRange FilenameRange,
const FileEntry *File,
80 llvm::StringRef SearchPath,
81 llvm::StringRef RelativePath,
const Module *Imported,
82 SrcMgr::CharacteristicKind FileType)
override {
83 auto IncludeURI = toURI(File);
87 auto IncludingURI = toURI(SM.getFileEntryForID(SM.getFileID(HashLoc)));
91 auto NodeForInclude = IG.try_emplace(*IncludeURI).first->getKey();
92 auto NodeForIncluding = IG.try_emplace(*IncludingURI);
94 NodeForIncluding.first->getValue().DirectIncludes.push_back(NodeForInclude);
98 void FileSkipped(
const FileEntry &SkippedFile,
const Token &FilenameTok,
99 SrcMgr::CharacteristicKind FileType)
override {
101 auto URI = toURI(&SkippedFile);
104 auto I = IG.try_emplace(*URI);
105 assert(!I.second &&
"File inserted for the first time on skip.");
106 assert(I.first->getKeyData() == I.first->getValue().URI.data() &&
107 "Node have not been populated yet");
112 const SourceManager &SM;
117 class IndexAction :
public WrapperFrontendAction {
119 IndexAction(std::shared_ptr<SymbolCollector> C,
120 std::unique_ptr<CanonicalIncludes> Includes,
121 const index::IndexingOptions &Opts,
122 std::function<
void(SymbolSlab)> SymbolsCallback,
123 std::function<
void(RefSlab)> RefsCallback,
124 std::function<
void(RelationSlab)> RelationsCallback,
126 : WrapperFrontendAction(index::createIndexingAction(C, Opts, nullptr)),
127 SymbolsCallback(SymbolsCallback), RefsCallback(RefsCallback),
128 RelationsCallback(RelationsCallback),
129 IncludeGraphCallback(IncludeGraphCallback),
Collector(C),
130 Includes(std::move(Includes)),
133 std::unique_ptr<ASTConsumer>
134 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile)
override {
137 if (IncludeGraphCallback !=
nullptr)
138 CI.getPreprocessor().addPPCallbacks(
139 llvm::make_unique<IncludeGraphCollector>(CI.getSourceManager(), IG));
140 return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
143 bool BeginInvocation(CompilerInstance &CI)
override {
145 CI.getLangOpts().CommentOpts.ParseAllComments =
true;
148 CI.getDiagnosticOpts().IgnoreWarnings =
true;
149 CI.getDiagnostics().setIgnoreAllWarnings(
true);
151 return WrapperFrontendAction::BeginInvocation(CI);
154 void EndSourceFileAction()
override {
155 WrapperFrontendAction::EndSourceFileAction();
157 SymbolsCallback(
Collector->takeSymbols());
158 if (RefsCallback !=
nullptr)
160 if (RelationsCallback !=
nullptr)
161 RelationsCallback(
Collector->takeRelations());
162 if (IncludeGraphCallback !=
nullptr) {
165 for (
const auto &Node : IG)
166 assert(Node.getKeyData() == Node.getValue().URI.data());
168 IncludeGraphCallback(std::move(IG));
173 std::function<void(SymbolSlab)> SymbolsCallback;
174 std::function<void(RefSlab)> RefsCallback;
175 std::function<void(RelationSlab)> RelationsCallback;
176 std::function<void(IncludeGraph)> IncludeGraphCallback;
177 std::shared_ptr<SymbolCollector>
Collector;
178 std::unique_ptr<CanonicalIncludes> Includes;
187 std::function<
void(
SymbolSlab)> SymbolsCallback,
188 std::function<
void(
RefSlab)> RefsCallback,
190 std::function<
void(
IncludeGraph)> IncludeGraphCallback) {
191 index::IndexingOptions IndexOpts;
192 IndexOpts.SystemSymbolFilter =
193 index::IndexingOptions::SystemSymbolFilterKind::All;
198 if (RefsCallback !=
nullptr) {
202 auto Includes = llvm::make_unique<CanonicalIncludes>();
204 return llvm::make_unique<IndexAction>(
205 std::make_shared<SymbolCollector>(std::move(Opts)), std::move(Includes),
206 IndexOpts, SymbolsCallback, RefsCallback, RelationsCallback,
207 IncludeGraphCallback);
std::unique_ptr< CommentHandler > collectIWYUHeaderMaps(CanonicalIncludes *Includes)
Returns a CommentHandler that parses pragma comment on include files to determine when we should incl...
SourceLocation Loc
'#' location in the include directive
An immutable symbol container that stores a set of symbols.
An efficient structure of storing large set of symbol references in memory.
void addSystemHeadersMapping(CanonicalIncludes *Includes, const LangOptions &Language)
Adds mapping for system headers and some special symbols (e.g.
Documents should not be synced at all.
llvm::StringMap< IncludeGraphNode > IncludeGraph
bool StoreAllDocumentation
If set to true, SymbolCollector will collect doc for all symbols.
bool IsAngled
true if this was an include with angle brackets
std::shared_ptr< SymbolCollector > Collector
llvm::Optional< FileDigest > digestFile(const SourceManager &SM, FileID FID)
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
bool RefsInHeaders
If set to true, SymbolCollector will collect all refs (from main file and included headers); otherwis...
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< FrontendAction > createStaticIndexingAction(SymbolCollector::Options Opts, std::function< void(SymbolSlab)> SymbolsCallback, std::function< void(RefSlab)> RefsCallback, std::function< void(RelationSlab)> RelationsCallback, std::function< void(IncludeGraph)> IncludeGraphCallback)
const CanonicalIncludes * Includes
If set, this is used to map symbol #include path to a potentially different #include path...
RefKind RefFilter
The symbol ref kinds that will be collected.
CommentHandler * PragmaHandler