Index: clang-tools-extra/clang-doc/BitcodeReader.cpp =================================================================== --- clang-tools-extra/clang-doc/BitcodeReader.cpp +++ clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -83,7 +83,7 @@ if (R[0] > INT_MAX) return llvm::make_error("Integer too large to parse.\n", llvm::inconvertibleErrorCode()); - Field.emplace((int)R[0], Blob); + Field.emplace((int)R[0], Blob, (bool)R[1]); return llvm::Error::success(); } @@ -129,7 +129,7 @@ if (R[0] > INT_MAX) return llvm::make_error("Integer too large to parse.\n", llvm::inconvertibleErrorCode()); - Field.emplace_back((int)R[0], Blob); + Field.emplace_back((int)R[0], Blob, (bool)R[1]); return llvm::Error::success(); } Index: clang-tools-extra/clang-doc/BitcodeWriter.cpp =================================================================== --- clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -77,10 +77,13 @@ {// 0. Fixed-size integer (line number) llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, BitCodeConstants::LineNumberSize), - // 1. Fixed-size integer (length of the following string (filename)) + // 1. Boolean (IsFileInRootDir) + llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, + BitCodeConstants::BoolSize), + // 2. Fixed-size integer (length of the following string (filename)) llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed, BitCodeConstants::StringLengthSize), - // 2. The string blob + // 3. The string blob llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)}); } @@ -314,6 +317,7 @@ // FIXME: Assert that the line number is of the appropriate size. Record.push_back(Loc.LineNumber); assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize)); + Record.push_back(Loc.IsFileInRootDir); Record.push_back(Loc.Filename.size()); Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename); } Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -269,12 +269,15 @@ return Out; } -static std::vector> genHTML(const EnumInfo &I); -static std::vector> genHTML(const FunctionInfo &I, - StringRef ParentInfoDir); +static std::vector> +genHTML(const EnumInfo &I, const ClangDocContext &CDCtx); +static std::vector> +genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, + StringRef ParentInfoDir); static std::vector> -genEnumsBlock(const std::vector &Enums) { +genEnumsBlock(const std::vector &Enums, + const ClangDocContext &CDCtx) { if (Enums.empty()) return {}; @@ -283,7 +286,7 @@ Out.emplace_back(llvm::make_unique(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &E : Enums) { - std::vector> Nodes = genHTML(E); + std::vector> Nodes = genHTML(E, CDCtx); AppendVector(std::move(Nodes), DivBody->Children); } return Out; @@ -302,7 +305,7 @@ static std::vector> genFunctionsBlock(const std::vector &Functions, - StringRef ParentInfoDir) { + const ClangDocContext &CDCtx, StringRef ParentInfoDir) { if (Functions.empty()) return {}; @@ -311,7 +314,8 @@ Out.emplace_back(llvm::make_unique(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &F : Functions) { - std::vector> Nodes = genHTML(F, ParentInfoDir); + std::vector> Nodes = + genHTML(F, CDCtx, ParentInfoDir); AppendVector(std::move(Nodes), DivBody->Children); } return Out; @@ -356,10 +360,27 @@ return Out; } -static std::unique_ptr writeFileDefinition(const Location &L) { - return llvm::make_unique( - HTMLTag::TAG_P, - "Defined at line " + std::to_string(L.LineNumber) + " of " + L.Filename); +static std::unique_ptr writeFileDefinition(const Location &L, + StringRef RepositoryUrl) { + if (!L.IsFileInRootDir || RepositoryUrl.empty()) + return llvm::make_unique( + HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) + + " of file " + L.Filename); + SmallString<128> FileURL(RepositoryUrl); + llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename); + auto Node = llvm::make_unique(HTMLTag::TAG_P); + Node->Children.emplace_back(llvm::make_unique("Defined at line ")); + auto LocNumberNode = + llvm::make_unique(HTMLTag::TAG_A, std::to_string(L.LineNumber)); + LocNumberNode->Attributes.try_emplace( + "href", (FileURL + "#" + std::to_string(L.LineNumber)).str()); + Node->Children.emplace_back(std::move(LocNumberNode)); + Node->Children.emplace_back(llvm::make_unique(" of file ")); + auto LocFileNode = llvm::make_unique( + HTMLTag::TAG_A, llvm::sys::path::filename(FileURL)); + LocFileNode->Attributes.try_emplace("href", FileURL); + Node->Children.emplace_back(std::move(LocFileNode)); + return Node; } static std::unique_ptr genHTML(const CommentInfo &I) { @@ -398,7 +419,8 @@ return CommentBlock; } -static std::vector> genHTML(const EnumInfo &I) { +static std::vector> +genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) { std::vector> Out; std::string EnumType; if (I.Scoped) @@ -414,7 +436,8 @@ Out.emplace_back(std::move(Node)); if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + Out.emplace_back( + writeFileDefinition(I.DefLoc.getValue(), CDCtx.RepositoryUrl)); std::string Description; if (!I.Description.empty()) @@ -423,8 +446,9 @@ return Out; } -static std::vector> genHTML(const FunctionInfo &I, - StringRef ParentInfoDir) { +static std::vector> +genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, + StringRef ParentInfoDir) { std::vector> Out; Out.emplace_back(llvm::make_unique(HTMLTag::TAG_H3, I.Name)); @@ -454,7 +478,8 @@ FunctionHeader->Children.emplace_back(llvm::make_unique(")")); if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + Out.emplace_back( + writeFileDefinition(I.DefLoc.getValue(), CDCtx.RepositoryUrl)); std::string Description; if (!I.Description.empty()) @@ -463,8 +488,9 @@ return Out; } -static std::vector> genHTML(const NamespaceInfo &I, - std::string &InfoTitle) { +static std::vector> +genHTML(const NamespaceInfo &I, const ClangDocContext &CDCtx, + std::string &InfoTitle) { std::vector> Out; if (I.Name.str() == "") InfoTitle = "Global Namespace"; @@ -485,23 +511,25 @@ AppendVector(std::move(ChildRecords), Out); std::vector> ChildFunctions = - genFunctionsBlock(I.ChildFunctions, I.Path); + genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path); AppendVector(std::move(ChildFunctions), Out); std::vector> ChildEnums = - genEnumsBlock(I.ChildEnums); + genEnumsBlock(I.ChildEnums, CDCtx); AppendVector(std::move(ChildEnums), Out); return Out; } -static std::vector> genHTML(const RecordInfo &I, - std::string &InfoTitle) { +static std::vector> +genHTML(const RecordInfo &I, const ClangDocContext &CDCtx, + std::string &InfoTitle) { std::vector> Out; InfoTitle = (getTagType(I.TagType) + " " + I.Name).str(); Out.emplace_back(llvm::make_unique(HTMLTag::TAG_H1, InfoTitle)); if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + Out.emplace_back( + writeFileDefinition(I.DefLoc.getValue(), CDCtx.RepositoryUrl)); std::string Description; if (!I.Description.empty()) @@ -534,10 +562,10 @@ AppendVector(std::move(ChildRecords), Out); std::vector> ChildFunctions = - genFunctionsBlock(I.ChildFunctions, I.Path); + genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path); AppendVector(std::move(ChildFunctions), Out); std::vector> ChildEnums = - genEnumsBlock(I.ChildEnums); + genEnumsBlock(I.ChildEnums, CDCtx); AppendVector(std::move(ChildEnums), Out); return Out; @@ -569,25 +597,25 @@ switch (I->IT) { case InfoType::IT_namespace: { std::vector> Nodes = - genHTML(*static_cast(I), InfoTitle); + genHTML(*static_cast(I), CDCtx, InfoTitle); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_record: { std::vector> Nodes = - genHTML(*static_cast(I), InfoTitle); + genHTML(*static_cast(I), CDCtx, InfoTitle); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_enum: { std::vector> Nodes = - genHTML(*static_cast(I)); + genHTML(*static_cast(I), CDCtx); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_function: { std::vector> Nodes = - genHTML(*static_cast(I), ""); + genHTML(*static_cast(I), CDCtx, ""); AppendVector(std::move(Nodes), MainContentNode->Children); break; } Index: clang-tools-extra/clang-doc/Mapper.h =================================================================== --- clang-tools-extra/clang-doc/Mapper.h +++ clang-tools-extra/clang-doc/Mapper.h @@ -44,7 +44,9 @@ template bool mapDecl(const T *D); int getLine(const NamedDecl *D, const ASTContext &Context) const; - StringRef getFile(const NamedDecl *D, const ASTContext &Context) const; + llvm::SmallString<128> getFile(const NamedDecl *D, const ASTContext &Context, + StringRef RootDir, + bool &IsFileInRootDir) const; comments::FullComment *getComment(const NamedDecl *D, const ASTContext &Context) const; Index: clang-tools-extra/clang-doc/Mapper.cpp =================================================================== --- clang-tools-extra/clang-doc/Mapper.cpp +++ clang-tools-extra/clang-doc/Mapper.cpp @@ -36,10 +36,11 @@ // If there is an error generating a USR for the decl, skip this decl. if (index::generateUSRForDecl(D, USR)) return true; - - auto I = serialize::emitInfo( - D, getComment(D, D->getASTContext()), getLine(D, D->getASTContext()), - getFile(D, D->getASTContext()), CDCtx.PublicOnly); + bool IsFileInRootDir; + auto File = getFile(D, D->getASTContext(), CDCtx.RootDir, IsFileInRootDir); + auto I = serialize::emitInfo(D, getComment(D, D->getASTContext()), + getLine(D, D->getASTContext()), File, + IsFileInRootDir, CDCtx.PublicOnly); // A null in place of I indicates that the serializer is skipping this decl // for some reason (e.g. we're only reporting public decls). @@ -87,11 +88,22 @@ return Context.getSourceManager().getPresumedLoc(D->getBeginLoc()).getLine(); } -llvm::StringRef MapASTVisitor::getFile(const NamedDecl *D, - const ASTContext &Context) const { - return Context.getSourceManager() - .getPresumedLoc(D->getBeginLoc()) - .getFilename(); +llvm::SmallString<128> MapASTVisitor::getFile(const NamedDecl *D, + const ASTContext &Context, + llvm::StringRef RootDir, + bool &IsFileInRootDir) const { + llvm::SmallString<128> File(Context.getSourceManager() + .getPresumedLoc(D->getBeginLoc()) + .getFilename()); + IsFileInRootDir = false; + if (RootDir.empty() || !File.startswith(RootDir)) + return File; + IsFileInRootDir = true; + llvm::SmallString<128> Prefix(RootDir); + if (!llvm::sys::path::is_separator(Prefix.back())) + Prefix += llvm::sys::path::get_separator(); + llvm::sys::path::replace_path_prefix(File, Prefix, ""); + return File; } } // namespace doc Index: clang-tools-extra/clang-doc/Representation.h =================================================================== --- clang-tools-extra/clang-doc/Representation.h +++ clang-tools-extra/clang-doc/Representation.h @@ -195,6 +195,9 @@ Location() = default; Location(int LineNumber, SmallString<16> Filename) : LineNumber(LineNumber), Filename(std::move(Filename)) {} + Location(int LineNumber, SmallString<16> Filename, bool IsFileInRootDir) + : LineNumber(LineNumber), Filename(std::move(Filename)), + IsFileInRootDir(IsFileInRootDir) {} bool operator==(const Location &Other) const { return std::tie(LineNumber, Filename) == @@ -210,8 +213,9 @@ std::tie(Other.LineNumber, Other.Filename); } - int LineNumber; // Line number of this Location. - SmallString<32> Filename; // File for this Location. + int LineNumber; // Line number of this Location. + SmallString<32> Filename; // File for this Location. + bool IsFileInRootDir = false; // Indicates if file is inside root directory }; /// A base struct for Infos. @@ -351,6 +355,8 @@ bool PublicOnly; std::string OutDirectory; std::vector UserStylesheets; + std::string RootDir; + std::string RepositoryUrl; }; } // namespace doc Index: clang-tools-extra/clang-doc/Serialize.h =================================================================== --- clang-tools-extra/clang-doc/Serialize.h +++ clang-tools-extra/clang-doc/Serialize.h @@ -38,19 +38,19 @@ // nullptr. std::pair, std::unique_ptr> emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair, std::unique_ptr> emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair, std::unique_ptr> emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair, std::unique_ptr> emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair, std::unique_ptr> emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); // Function to hash a given USR value for storage. // As USRs (Unified Symbol Resolution) could be large, especially for functions Index: clang-tools-extra/clang-doc/Serialize.cpp =================================================================== --- clang-tools-extra/clang-doc/Serialize.cpp +++ clang-tools-extra/clang-doc/Serialize.cpp @@ -348,19 +348,21 @@ template static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, int LineNumber, StringRef Filename, + bool IsFileInRootDir, bool &IsInAnonymousNamespace) { populateInfo(I, D, C, IsInAnonymousNamespace); if (D->isThisDeclarationADefinition()) - I.DefLoc.emplace(LineNumber, Filename); + I.DefLoc.emplace(LineNumber, Filename, IsFileInRootDir); else - I.Loc.emplace_back(LineNumber, Filename); + I.Loc.emplace_back(LineNumber, Filename, IsFileInRootDir); } static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D, const FullComment *FC, int LineNumber, - StringRef Filename, + StringRef Filename, bool IsFileInRootDir, bool &IsInAnonymousNamespace) { - populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace); + populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir, + IsInAnonymousNamespace); if (const auto *T = getDeclForType(D->getReturnType())) { if (dyn_cast(T)) I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(), @@ -376,7 +378,7 @@ std::pair, std::unique_ptr> emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool PublicOnly) { + llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { auto I = llvm::make_unique(); bool IsInAnonymousNamespace = false; populateInfo(*I, D, FC, IsInAnonymousNamespace); @@ -402,10 +404,11 @@ std::pair, std::unique_ptr> emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool PublicOnly) { + llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { auto I = llvm::make_unique(); bool IsInAnonymousNamespace = false; - populateSymbolInfo(*I, D, FC, LineNumber, File, IsInAnonymousNamespace); + populateSymbolInfo(*I, D, FC, LineNumber, File, IsFileInRootDir, + IsInAnonymousNamespace); if (PublicOnly && ((IsInAnonymousNamespace || !isPublic(D->getAccess(), D->getLinkageInternal())))) return {}; @@ -452,10 +455,11 @@ std::pair, std::unique_ptr> emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool PublicOnly) { + llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; - populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace); + populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, + IsInAnonymousNamespace); if (PublicOnly && ((IsInAnonymousNamespace || !isPublic(D->getAccess(), D->getLinkageInternal())))) return {}; @@ -477,10 +481,11 @@ std::pair, std::unique_ptr> emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool PublicOnly) { + llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { FunctionInfo Func; bool IsInAnonymousNamespace = false; - populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace); + populateFunctionInfo(Func, D, FC, LineNumber, File, IsFileInRootDir, + IsInAnonymousNamespace); if (PublicOnly && ((IsInAnonymousNamespace || !isPublic(D->getAccess(), D->getLinkageInternal())))) return {}; @@ -511,10 +516,11 @@ std::pair, std::unique_ptr> emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File, bool PublicOnly) { + llvm::StringRef File, bool IsFileInRootDir, bool PublicOnly) { EnumInfo Enum; bool IsInAnonymousNamespace = false; - populateSymbolInfo(Enum, D, FC, LineNumber, File, IsInAnonymousNamespace); + populateSymbolInfo(Enum, D, FC, LineNumber, File, IsFileInRootDir, + IsInAnonymousNamespace); if (PublicOnly && ((IsInAnonymousNamespace || !isPublic(D->getAccess(), D->getLinkageInternal())))) return {}; Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp =================================================================== --- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -67,6 +67,19 @@ llvm::cl::desc("CSS stylesheets to extend the default styles."), llvm::cl::cat(ClangDocCategory)); +static llvm::cl::opt RootDirectory( + "root-directory", + llvm::cl::desc( + "Directory where processed files are stored. Links to definition " + "locations will only be generated if the file is in this dir."), + llvm::cl::cat(ClangDocCategory)); + +static llvm::cl::opt + RepositoryUrl("repository", + llvm::cl::desc("URL of repository that hosts code; used for " + "links to definition locations."), + llvm::cl::cat(ClangDocCategory)); + enum OutputFormatTy { md, yaml, @@ -133,7 +146,7 @@ // /A/B/C. // // namespace A { -// namesapce B { +// namespace B { // // class C {}; // @@ -206,11 +219,21 @@ tooling::ArgumentInsertPosition::END), ArgAdjuster); + llvm::SmallString<128> RootDir(RootDirectory); + if (RootDir.empty()) + llvm::sys::fs::current_path(RootDir); + + if (!RepositoryUrl.empty() && RepositoryUrl.find("http://") != 0 && + RepositoryUrl.find("https://") != 0) + RepositoryUrl.insert(0, "http://"); + clang::doc::ClangDocContext CDCtx = { Exec->get()->getExecutionContext(), PublicOnly, OutDirectory, - {UserStylesheets.begin(), UserStylesheets.end()}}; + {UserStylesheets.begin(), UserStylesheets.end()}, + RootDir.str(), + RepositoryUrl}; if (Format == "html") { void *MainAddr = (void *)(intptr_t)GetExecutablePath; Index: clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp =================================================================== --- clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -22,12 +22,14 @@ } ClangDocContext -getClangDocContext(std::vector UserStylesheets = {}) { +getClangDocContext(std::vector UserStylesheets = {}, + StringRef RepositoryUrl = "") { ClangDocContext CDCtx; CDCtx.UserStylesheets = {UserStylesheets.begin(), UserStylesheets.end()}; CDCtx.UserStylesheets.insert( CDCtx.UserStylesheets.begin(), "../share/clang/clang-doc-default-stylesheet.css"); + CDCtx.RepositoryUrl = RepositoryUrl; return CDCtx; } @@ -87,7 +89,7 @@ I.Path = "X/Y/Z"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); + I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, true); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); SmallString<16> PathTo; @@ -107,7 +109,7 @@ assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext(); + ClangDocContext CDCtx = getClangDocContext({}, "https://www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw( @@ -116,7 +118,12 @@

class r

-

Defined at line 10 of test.cpp

+

+ Defined at line + 10 + of file + test.cpp +

Inherits from F @@ -154,7 +161,7 @@ I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); + I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, false); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); SmallString<16> PathTo; @@ -168,7 +175,7 @@ assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext(); + ClangDocContext CDCtx = getClangDocContext({}, "https://www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw( @@ -183,7 +190,7 @@ int P)

-

Defined at line 10 of test.cpp

+

Defined at line 10 of file dir/test.cpp

)raw"; @@ -217,7 +224,7 @@
  • X
-

Defined at line 10 of test.cpp

+

Defined at line 10 of file test.cpp

)raw"; @@ -284,7 +291,7 @@

f

void f(int I, int J)

-

Defined at line 10 of test.cpp

+

Defined at line 10 of file test.cpp

Brief description.

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp =================================================================== --- clang-tools-extra/unittests/clang-doc/SerializeTest.cpp +++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp @@ -37,7 +37,7 @@ template bool mapDecl(const T *D) { auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0, - /*File=*/"test.cpp", Public); + /*File=*/"test.cpp", true, Public); if (I.first) EmittedInfos.emplace_back(std::move(I.first)); if (I.second)