14 #include "clang/Frontend/CompilerInstance.h" 15 #include "clang/Frontend/CompilerInvocation.h" 16 #include "clang/Frontend/FrontendActions.h" 17 #include "clang/Lex/HeaderSearch.h" 18 #include "llvm/Support/Path.h" 26 RecordHeaders(
const SourceManager &SM, IncludeStructure *Out)
31 void InclusionDirective(SourceLocation HashLoc,
const Token & ,
33 CharSourceRange FilenameRange,
const FileEntry *
File,
37 SrcMgr::CharacteristicKind )
override {
38 if (SM.isInMainFile(HashLoc))
39 Out->MainFileIncludes.push_back({
40 halfOpenToRange(SM, FilenameRange),
41 (IsAngled ?
"<" + FileName +
">" :
"\"" + FileName +
"\"").str(),
42 File ? File->tryGetRealPathName() :
"",
45 auto *IncludingFileEntry = SM.getFileEntryForID(SM.getFileID(HashLoc));
46 if (!IncludingFileEntry) {
47 assert(SM.getBufferName(HashLoc).startswith(
"<") &&
48 "Expected #include location to be a file or <built-in>");
50 IncludingFileEntry = SM.getFileEntryForID(SM.getMainFileID());
52 Out->recordInclude(IncludingFileEntry->getName(), File->getName(),
53 File->tryGetRealPathName());
58 const SourceManager &SM;
59 IncludeStructure *Out;
65 return Include.startswith(
"<") || Include.startswith(
"\"");
70 (!Verbatim && llvm::sys::path::is_absolute(File));
73 std::unique_ptr<PPCallbacks>
76 return llvm::make_unique<RecordHeaders>(SM, Out);
80 llvm::StringRef IncludedName,
81 llvm::StringRef IncludedRealName) {
82 auto Child = fileIndex(IncludedName);
83 if (!IncludedRealName.empty() && RealPathNames[Child].empty())
84 RealPathNames[Child] = IncludedRealName;
85 auto Parent = fileIndex(IncludingName);
86 IncludeChildren[Parent].push_back(Child);
89 unsigned IncludeStructure::fileIndex(llvm::StringRef
Name) {
90 auto R = NameToIndex.try_emplace(Name, RealPathNames.size());
92 RealPathNames.emplace_back();
93 return R.first->getValue();
96 llvm::StringMap<unsigned>
99 llvm::StringMap<unsigned> Result;
101 std::vector<unsigned> CurrentLevel;
102 llvm::DenseSet<unsigned> Seen;
103 auto It = NameToIndex.find(Root);
104 if (It != NameToIndex.end()) {
105 CurrentLevel.push_back(It->second);
106 Seen.insert(It->second);
110 std::vector<unsigned> PreviousLevel;
111 for (
unsigned Level = 1; !CurrentLevel.empty(); ++Level) {
112 PreviousLevel.clear();
113 PreviousLevel.swap(CurrentLevel);
114 for (
const auto &Parent : PreviousLevel) {
115 for (
const auto &Child : IncludeChildren.lookup(Parent)) {
116 if (Seen.insert(Child).second) {
117 CurrentLevel.push_back(Child);
118 const auto &Name = RealPathNames[Child];
121 Result[Name] = Level;
133 assert(DeclaringHeader.
valid() && InsertedHeader.
valid());
134 if (FileName == DeclaringHeader.
File || FileName == InsertedHeader.
File)
136 llvm::StringSet<> IncludedHeaders;
137 for (
const auto &Inc : Inclusions) {
138 IncludedHeaders.insert(Inc.Written);
139 if (!Inc.Resolved.empty())
140 IncludedHeaders.insert(Inc.Resolved);
142 auto Included = [&](llvm::StringRef Header) {
143 return IncludedHeaders.find(Header) != IncludedHeaders.end();
145 return !Included(DeclaringHeader.
File) && !Included(InsertedHeader.
File);
151 assert(DeclaringHeader.
valid() && InsertedHeader.
valid());
153 return InsertedHeader.
File;
154 bool IsSystem =
false;
155 std::string Suggested = HeaderSearchInfo.suggestPathToFileForDiagnostics(
156 InsertedHeader.
File, BuildDir, &IsSystem);
158 Suggested =
"<" + Suggested +
">";
160 Suggested =
"\"" + Suggested +
"\"";
165 Optional<TextEdit> Edit =
None;
166 if (
auto Insertion = Inserter.insert(VerbatimHeader.trim(
"\"<>"),
167 VerbatimHeader.startswith(
"<")))
Documents should not be synced at all.
TextEdit replacementToEdit(StringRef Code, const tooling::Replacement &R)
bool IsAngled
true if this was an include with angle brackets
bool shouldInsertInclude(const HeaderFile &DeclaringHeader, const HeaderFile &InsertedHeader) const
Checks whether to add an #include of the header into File.
void recordInclude(llvm::StringRef IncludingName, llvm::StringRef IncludedName, llvm::StringRef IncludedRealName)
std::string calculateIncludePath(const HeaderFile &DeclaringHeader, const HeaderFile &InsertedHeader) const
Determines the preferred way to #include a file, taking into account the search path.
std::unique_ptr< PPCallbacks > collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out)
Returns a PPCallback that visits all inclusions in the main file.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::StringMap< unsigned > includeDepth(llvm::StringRef Root) const
llvm::Optional< TextEdit > insert(llvm::StringRef VerbatimHeader) const
Calculates an edit that inserts VerbatimHeader into code.
bool isLiteralInclude(llvm::StringRef Include)
Returns true if Include is literal include like "path" or <path>.