14 #include "clang/AST/ASTConsumer.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/Basic/SourceLocation.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "clang/Frontend/CompilerInstance.h" 19 #include "clang/Frontend/MultiplexConsumer.h" 20 #include "clang/Index/IndexingAction.h" 21 #include "clang/Index/IndexingOptions.h" 22 #include "clang/Tooling/Tooling.h" 23 #include "llvm/ADT/STLExtras.h" 32 llvm::Optional<std::string> toURI(
const FileEntry *File) {
35 auto AbsolutePath = File->tryGetRealPathName();
36 if (AbsolutePath.empty())
46 IncludeGraphCollector(
const SourceManager &SM,
IncludeGraph &IG)
53 void FileChanged(SourceLocation
Loc, FileChangeReason Reason,
54 SrcMgr::CharacteristicKind FileType,
55 FileID PrevFID)
override {
58 if (Reason != FileChangeReason::EnterFile)
61 const auto FileID = SM.getFileID(Loc);
62 const auto File = SM.getFileEntryForID(FileID);
63 auto URI = toURI(File);
66 auto I = IG.try_emplace(*URI).first;
68 auto &Node = I->getValue();
70 if (Node.URI.data() == I->getKeyData()) {
73 assert(Digest && Node.Digest == *Digest &&
74 "Same file, different digest?");
79 Node.Digest = std::move(*Digest);
80 if (FileID == SM.getMainFileID())
82 Node.URI = I->getKey();
86 void InclusionDirective(SourceLocation HashLoc,
const Token &IncludeTok,
88 CharSourceRange FilenameRange,
const FileEntry *File,
89 llvm::StringRef SearchPath,
90 llvm::StringRef RelativePath,
const Module *Imported,
91 SrcMgr::CharacteristicKind FileType)
override {
92 auto IncludeURI = toURI(File);
96 auto IncludingURI = toURI(SM.getFileEntryForID(SM.getFileID(HashLoc)));
100 auto NodeForInclude = IG.try_emplace(*IncludeURI).first->getKey();
101 auto NodeForIncluding = IG.try_emplace(*IncludingURI);
103 NodeForIncluding.first->getValue().DirectIncludes.push_back(NodeForInclude);
107 void FileSkipped(
const FileEntryRef &SkippedFile,
const Token &FilenameTok,
108 SrcMgr::CharacteristicKind FileType)
override {
110 auto URI = toURI(&SkippedFile.getFileEntry());
113 auto I = IG.try_emplace(*URI);
114 assert(!I.second &&
"File inserted for the first time on skip.");
115 assert(I.first->getKeyData() == I.first->getValue().URI.data() &&
116 "Node have not been populated yet");
121 const SourceManager &SM;
126 class IndexAction :
public ASTFrontendAction {
128 IndexAction(std::shared_ptr<SymbolCollector> C,
129 std::unique_ptr<CanonicalIncludes> Includes,
130 const index::IndexingOptions &Opts,
131 std::function<
void(SymbolSlab)> SymbolsCallback,
132 std::function<
void(RefSlab)> RefsCallback,
133 std::function<
void(RelationSlab)> RelationsCallback,
135 : SymbolsCallback(SymbolsCallback),
136 RefsCallback(RefsCallback), RelationsCallback(RelationsCallback),
137 IncludeGraphCallback(IncludeGraphCallback),
Collector(C),
138 Includes(std::move(Includes)), Opts(Opts),
141 std::unique_ptr<ASTConsumer>
142 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile)
override {
144 Includes->addSystemHeadersMapping(CI.getLangOpts());
145 if (IncludeGraphCallback !=
nullptr)
146 CI.getPreprocessor().addPPCallbacks(
147 std::make_unique<IncludeGraphCollector>(CI.getSourceManager(), IG));
149 return index::createIndexingASTConsumer(
150 Collector, Opts, CI.getPreprocessorPtr(),
151 [
this](
const Decl *D) {
152 auto &SM = D->getASTContext().getSourceManager();
153 auto FID = SM.getFileID(SM.getExpansionLoc(D->getLocation()));
160 bool BeginInvocation(CompilerInstance &CI)
override {
162 CI.getLangOpts().CommentOpts.ParseAllComments =
true;
163 CI.getLangOpts().RetainCommentsFromSystemHeaders =
true;
166 CI.getDiagnosticOpts().IgnoreWarnings =
true;
167 CI.getDiagnostics().setIgnoreAllWarnings(
true);
171 CI.getFrontendOpts().SkipFunctionBodies =
true;
175 void EndSourceFileAction()
override {
176 SymbolsCallback(
Collector->takeSymbols());
177 if (RefsCallback !=
nullptr)
179 if (RelationsCallback !=
nullptr)
180 RelationsCallback(
Collector->takeRelations());
181 if (IncludeGraphCallback !=
nullptr) {
184 for (
const auto &Node : IG)
185 assert(Node.getKeyData() == Node.getValue().URI.data());
187 IncludeGraphCallback(std::move(IG));
192 std::function<void(SymbolSlab)> SymbolsCallback;
193 std::function<void(RefSlab)> RefsCallback;
194 std::function<void(RelationSlab)> RelationsCallback;
195 std::function<void(IncludeGraph)> IncludeGraphCallback;
196 std::shared_ptr<SymbolCollector>
Collector;
197 std::unique_ptr<CanonicalIncludes> Includes;
198 index::IndexingOptions Opts;
207 std::function<
void(
SymbolSlab)> SymbolsCallback,
208 std::function<
void(
RefSlab)> RefsCallback,
210 std::function<
void(
IncludeGraph)> IncludeGraphCallback) {
211 index::IndexingOptions IndexOpts;
212 IndexOpts.SystemSymbolFilter =
213 index::IndexingOptions::SystemSymbolFilterKind::All;
218 if (RefsCallback !=
nullptr) {
222 auto Includes = std::make_unique<CanonicalIncludes>();
224 return std::make_unique<IndexAction>(
225 std::make_shared<SymbolCollector>(std::move(Opts)), std::move(Includes),
226 IndexOpts, SymbolsCallback, RefsCallback, RelationsCallback,
227 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
const FunctionDecl * Decl
An immutable symbol container that stores a set of symbols.
An efficient structure of storing large set of symbol references in memory.
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