2 #include "clang/Frontend/CompilerInstance.h" 3 #include "clang/Index/IndexDataConsumer.h" 4 #include "clang/Index/IndexingAction.h" 5 #include "clang/Tooling/Tooling.h" 11 llvm::Optional<std::string> toURI(
const FileEntry *File) {
14 auto AbsolutePath = File->tryGetRealPathName();
15 if (AbsolutePath.empty())
25 IncludeGraphCollector(
const SourceManager &SM,
IncludeGraph &IG)
32 void FileChanged(SourceLocation
Loc, FileChangeReason Reason,
33 SrcMgr::CharacteristicKind FileType,
34 FileID PrevFID)
override {
37 if (Reason != FileChangeReason::EnterFile)
40 const auto FileID = SM.getFileID(Loc);
41 const auto File = SM.getFileEntryForID(FileID);
42 auto URI = toURI(File);
45 auto I = IG.try_emplace(*URI).first;
47 auto &Node = I->getValue();
49 if (Node.URI.data() == I->getKeyData()) {
52 assert(Digest && Node.Digest == *Digest &&
53 "Same file, different digest?");
58 Node.Digest = std::move(*Digest);
59 Node.IsTU = FileID == SM.getMainFileID();
60 Node.URI = I->getKey();
64 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
66 CharSourceRange FilenameRange,
const FileEntry *File,
67 llvm::StringRef SearchPath,
68 llvm::StringRef RelativePath,
const Module *Imported,
69 SrcMgr::CharacteristicKind FileType)
override {
70 auto IncludeURI = toURI(File);
74 auto IncludingURI = toURI(SM.getFileEntryForID(SM.getFileID(HashLoc)));
78 auto NodeForInclude = IG.try_emplace(*IncludeURI).first->getKey();
79 auto NodeForIncluding = IG.try_emplace(*IncludingURI);
81 NodeForIncluding.first->getValue().DirectIncludes.push_back(NodeForInclude);
85 void FileSkipped(
const FileEntry &SkippedFile,
const Token &FilenameTok,
86 SrcMgr::CharacteristicKind FileType)
override {
88 auto URI = toURI(&SkippedFile);
91 auto I = IG.try_emplace(*URI);
92 assert(!I.second &&
"File inserted for the first time on skip.");
93 assert(I.first->getKeyData() == I.first->getValue().URI.data() &&
94 "Node have not been populated yet");
99 const SourceManager &SM;
104 class IndexAction :
public WrapperFrontendAction {
106 IndexAction(std::shared_ptr<SymbolCollector> C,
107 std::unique_ptr<CanonicalIncludes> Includes,
108 const index::IndexingOptions &Opts,
109 std::function<
void(SymbolSlab)> SymbolsCallback,
110 std::function<
void(RefSlab)> RefsCallback,
112 : WrapperFrontendAction(index::createIndexingAction(C, Opts, nullptr)),
113 SymbolsCallback(SymbolsCallback), RefsCallback(RefsCallback),
114 IncludeGraphCallback(IncludeGraphCallback), Collector(C),
115 Includes(std::move(Includes)),
118 std::unique_ptr<ASTConsumer>
119 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile)
override {
120 CI.getPreprocessor().addCommentHandler(PragmaHandler.get());
121 if (IncludeGraphCallback !=
nullptr)
122 CI.getPreprocessor().addPPCallbacks(
123 llvm::make_unique<IncludeGraphCollector>(CI.getSourceManager(), IG));
124 return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
127 bool BeginInvocation(CompilerInstance &CI)
override {
129 CI.getLangOpts().CommentOpts.ParseAllComments =
true;
130 return WrapperFrontendAction::BeginInvocation(CI);
133 void EndSourceFileAction()
override {
134 WrapperFrontendAction::EndSourceFileAction();
136 const auto &CI = getCompilerInstance();
137 if (CI.hasDiagnostics() &&
138 CI.getDiagnostics().hasUncompilableErrorOccurred()) {
139 llvm::errs() <<
"Skipping TU due to uncompilable errors\n";
142 SymbolsCallback(Collector->takeSymbols());
143 if (RefsCallback !=
nullptr)
144 RefsCallback(Collector->takeRefs());
145 if (IncludeGraphCallback !=
nullptr) {
148 for (
const auto &Node : IG)
149 assert(Node.getKeyData() == Node.getValue().URI.data());
151 IncludeGraphCallback(std::move(IG));
156 std::function<void(SymbolSlab)> SymbolsCallback;
157 std::function<void(RefSlab)> RefsCallback;
158 std::function<void(IncludeGraph)> IncludeGraphCallback;
159 std::shared_ptr<SymbolCollector> Collector;
160 std::unique_ptr<CanonicalIncludes> Includes;
161 std::unique_ptr<CommentHandler> PragmaHandler;
169 std::function<
void(
SymbolSlab)> SymbolsCallback,
170 std::function<
void(
RefSlab)> RefsCallback,
171 std::function<
void(
IncludeGraph)> IncludeGraphCallback) {
172 index::IndexingOptions IndexOpts;
173 IndexOpts.SystemSymbolFilter =
174 index::IndexingOptions::SystemSymbolFilterKind::All;
178 if (RefsCallback !=
nullptr) {
182 auto Includes = llvm::make_unique<CanonicalIncludes>();
185 return llvm::make_unique<IndexAction>(
186 std::make_shared<SymbolCollector>(std::move(Opts)), std::move(Includes),
187 IndexOpts, SymbolsCallback, RefsCallback, 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
Documents should not be synced at all.
llvm::StringMap< IncludeGraphNode > IncludeGraph
bool IsAngled
true if this was an include with angle brackets
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(IncludeGraph)> IncludeGraphCallback)
void addSystemHeadersMapping(CanonicalIncludes *Includes)
Adds mapping for system headers and some special symbols (e.g.
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.