Author: diegoastiazaran Date: Fri Aug 9 10:49:41 2019 New Revision: 368460
URL: http://llvm.org/viewvc/llvm-project?rev=368460&view=rev Log: [clang-format] Add link to source code in file definitions Two command line options have been added to clang-doc. --repository=<string> - URL of repository that hosts code; used for links to definition locations. --source-root=<string> - Directory where processed files are stored. Links to definition locations will only be generated if the file is in this dir. If the file is in the source-root and a repository options is passed; a link to the source code will be rendered by the HTML generator. Differential Revision: https://reviews.llvm.org/D65483 Modified: clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp clang-tools-extra/trunk/clang-doc/Mapper.cpp clang-tools-extra/trunk/clang-doc/Mapper.h clang-tools-extra/trunk/clang-doc/Representation.cpp clang-tools-extra/trunk/clang-doc/Representation.h clang-tools-extra/trunk/clang-doc/Serialize.cpp clang-tools-extra/trunk/clang-doc/Serialize.h clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp clang-tools-extra/trunk/docs/clang-doc.rst clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp Modified: clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp (original) +++ clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp Fri Aug 9 10:49:41 2019 @@ -83,7 +83,7 @@ llvm::Error decodeRecord(Record R, llvm: if (R[0] > INT_MAX) return llvm::make_error<llvm::StringError>("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 @@ llvm::Error decodeRecord(Record R, llvm: if (R[0] > INT_MAX) return llvm::make_error<llvm::StringError>("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(); } Modified: clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp (original) +++ clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp Fri Aug 9 10:49:41 2019 @@ -77,10 +77,13 @@ static void LocationAbbrev(std::shared_p {// 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)}); } @@ -316,6 +319,7 @@ void ClangDocBitcodeWriter::emitRecord(c // 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); } Modified: clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp (original) +++ clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp Fri Aug 9 10:49:41 2019 @@ -301,12 +301,15 @@ genReferenceList(const llvm::SmallVector return Out; } -static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I); -static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I, - StringRef ParentInfoDir); +static std::vector<std::unique_ptr<TagNode>> +genHTML(const EnumInfo &I, const ClangDocContext &CDCtx); +static std::vector<std::unique_ptr<TagNode>> +genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, + StringRef ParentInfoDir); static std::vector<std::unique_ptr<TagNode>> -genEnumsBlock(const std::vector<EnumInfo> &Enums) { +genEnumsBlock(const std::vector<EnumInfo> &Enums, + const ClangDocContext &CDCtx) { if (Enums.empty()) return {}; @@ -316,7 +319,7 @@ genEnumsBlock(const std::vector<EnumInfo Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &E : Enums) { - std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E); + std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E, CDCtx); AppendVector(std::move(Nodes), DivBody->Children); } return Out; @@ -335,7 +338,7 @@ genEnumMembersBlock(const llvm::SmallVec static std::vector<std::unique_ptr<TagNode>> genFunctionsBlock(const std::vector<FunctionInfo> &Functions, - StringRef ParentInfoDir) { + const ClangDocContext &CDCtx, StringRef ParentInfoDir) { if (Functions.empty()) return {}; @@ -345,7 +348,8 @@ genFunctionsBlock(const std::vector<Func Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV)); auto &DivBody = Out.back(); for (const auto &F : Functions) { - std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F, ParentInfoDir); + std::vector<std::unique_ptr<TagNode>> Nodes = + genHTML(F, CDCtx, ParentInfoDir); AppendVector(std::move(Nodes), DivBody->Children); } return Out; @@ -392,10 +396,30 @@ genReferencesBlock(const std::vector<Ref return Out; } -static std::unique_ptr<TagNode> writeFileDefinition(const Location &L) { - return llvm::make_unique<TagNode>( - HTMLTag::TAG_P, - "Defined at line " + std::to_string(L.LineNumber) + " of " + L.Filename); +static std::unique_ptr<TagNode> +writeFileDefinition(const Location &L, + llvm::Optional<StringRef> RepositoryUrl = None) { + if (!L.IsFileInRootDir || !RepositoryUrl) + return llvm::make_unique<TagNode>( + HTMLTag::TAG_P, "Defined at line " + std::to_string(L.LineNumber) + + " of file " + L.Filename); + SmallString<128> FileURL(RepositoryUrl.getValue()); + llvm::sys::path::append(FileURL, llvm::sys::path::Style::posix, L.Filename); + auto Node = llvm::make_unique<TagNode>(HTMLTag::TAG_P); + Node->Children.emplace_back(llvm::make_unique<TextNode>("Defined at line ")); + auto LocNumberNode = + llvm::make_unique<TagNode>(HTMLTag::TAG_A, std::to_string(L.LineNumber)); + // The links to a specific line in the source code use the github / + // googlesource notation so it won't work for all hosting pages. + 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<TextNode>(" of file ")); + auto LocFileNode = llvm::make_unique<TagNode>( + 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::vector<std::unique_ptr<TagNode>> @@ -491,7 +515,8 @@ static std::unique_ptr<TagNode> genHTML( return CommentBlock; } -static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I) { +static std::vector<std::unique_ptr<TagNode>> +genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) { std::vector<std::unique_ptr<TagNode>> Out; std::string EnumType; if (I.Scoped) @@ -508,8 +533,13 @@ static std::vector<std::unique_ptr<TagNo if (Node) Out.emplace_back(std::move(Node)); - if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + if (I.DefLoc) { + if (!CDCtx.RepositoryUrl) + Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + else + Out.emplace_back(writeFileDefinition( + I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()})); + } std::string Description; if (!I.Description.empty()) @@ -518,8 +548,9 @@ static std::vector<std::unique_ptr<TagNo return Out; } -static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I, - StringRef ParentInfoDir) { +static std::vector<std::unique_ptr<TagNode>> +genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, + StringRef ParentInfoDir) { std::vector<std::unique_ptr<TagNode>> Out; Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name)); // USR is used as id for functions instead of name to disambiguate function @@ -552,8 +583,13 @@ static std::vector<std::unique_ptr<TagNo } FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(")")); - if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + if (I.DefLoc) { + if (!CDCtx.RepositoryUrl) + Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + else + Out.emplace_back(writeFileDefinition( + I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()})); + } std::string Description; if (!I.Description.empty()) @@ -563,7 +599,8 @@ static std::vector<std::unique_ptr<TagNo } static std::vector<std::unique_ptr<TagNode>> -genHTML(const NamespaceInfo &I, Index &InfoIndex, std::string &InfoTitle) { +genHTML(const NamespaceInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, + std::string &InfoTitle) { std::vector<std::unique_ptr<TagNode>> Out; if (I.Name.str() == "") InfoTitle = "Global Namespace"; @@ -584,10 +621,10 @@ genHTML(const NamespaceInfo &I, Index &I AppendVector(std::move(ChildRecords), Out); std::vector<std::unique_ptr<TagNode>> ChildFunctions = - genFunctionsBlock(I.ChildFunctions, I.Path); + genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path); AppendVector(std::move(ChildFunctions), Out); std::vector<std::unique_ptr<TagNode>> ChildEnums = - genEnumsBlock(I.ChildEnums); + genEnumsBlock(I.ChildEnums, CDCtx); AppendVector(std::move(ChildEnums), Out); if (!I.ChildNamespaces.empty()) @@ -604,13 +641,19 @@ genHTML(const NamespaceInfo &I, Index &I } static std::vector<std::unique_ptr<TagNode>> -genHTML(const RecordInfo &I, Index &InfoIndex, std::string &InfoTitle) { +genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, + std::string &InfoTitle) { std::vector<std::unique_ptr<TagNode>> Out; InfoTitle = (getTagType(I.TagType) + " " + I.Name).str(); Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle)); - if (I.DefLoc) - Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + if (I.DefLoc) { + if (!CDCtx.RepositoryUrl) + Out.emplace_back(writeFileDefinition(I.DefLoc.getValue())); + else + Out.emplace_back(writeFileDefinition( + I.DefLoc.getValue(), StringRef{CDCtx.RepositoryUrl.getValue()})); + } std::string Description; if (!I.Description.empty()) @@ -643,10 +686,10 @@ genHTML(const RecordInfo &I, Index &Info AppendVector(std::move(ChildRecords), Out); std::vector<std::unique_ptr<TagNode>> ChildFunctions = - genFunctionsBlock(I.ChildFunctions, I.Path); + genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path); AppendVector(std::move(ChildFunctions), Out); std::vector<std::unique_ptr<TagNode>> ChildEnums = - genEnumsBlock(I.ChildEnums); + genEnumsBlock(I.ChildEnums, CDCtx); AppendVector(std::move(ChildEnums), Out); if (!I.Members.empty()) @@ -682,26 +725,27 @@ llvm::Error HTMLGenerator::generateDocFo Index InfoIndex; switch (I->IT) { case InfoType::IT_namespace: { - std::vector<std::unique_ptr<TagNode>> Nodes = genHTML( - *static_cast<clang::doc::NamespaceInfo *>(I), InfoIndex, InfoTitle); + std::vector<std::unique_ptr<TagNode>> Nodes = + genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), InfoIndex, CDCtx, + InfoTitle); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_record: { std::vector<std::unique_ptr<TagNode>> Nodes = genHTML( - *static_cast<clang::doc::RecordInfo *>(I), InfoIndex, InfoTitle); + *static_cast<clang::doc::RecordInfo *>(I), InfoIndex, CDCtx, InfoTitle); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_enum: { std::vector<std::unique_ptr<TagNode>> Nodes = - genHTML(*static_cast<clang::doc::EnumInfo *>(I)); + genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx); AppendVector(std::move(Nodes), MainContentNode->Children); break; } case InfoType::IT_function: { std::vector<std::unique_ptr<TagNode>> Nodes = - genHTML(*static_cast<clang::doc::FunctionInfo *>(I), ""); + genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, ""); AppendVector(std::move(Nodes), MainContentNode->Children); break; } Modified: clang-tools-extra/trunk/clang-doc/Mapper.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Mapper.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Mapper.cpp (original) +++ clang-tools-extra/trunk/clang-doc/Mapper.cpp Fri Aug 9 10:49:41 2019 @@ -36,10 +36,12 @@ template <typename T> bool MapASTVisitor // 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; + llvm::SmallString<128> File = + getFile(D, D->getASTContext(), CDCtx.SourceRoot, 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 +89,26 @@ int MapASTVisitor::getLine(const NamedDe 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); + // replace_path_prefix removes the exact prefix provided. The result of + // calling that function on ("A/B/C.c", "A/B", "") would be "/C.c", which + // starts with a / that is not needed. This is why we fix Prefix so it always + // ends with a / and the result has the desired format. + 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 Modified: clang-tools-extra/trunk/clang-doc/Mapper.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Mapper.h?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Mapper.h (original) +++ clang-tools-extra/trunk/clang-doc/Mapper.h Fri Aug 9 10:49:41 2019 @@ -44,7 +44,9 @@ private: template <typename T> 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; Modified: clang-tools-extra/trunk/clang-doc/Representation.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Representation.cpp (original) +++ clang-tools-extra/trunk/clang-doc/Representation.cpp Fri Aug 9 10:49:41 2019 @@ -235,5 +235,21 @@ void Index::sort() { C.sort(); } +ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, + bool PublicOnly, StringRef OutDirectory, + StringRef SourceRoot, StringRef RepositoryUrl, + std::vector<std::string> UserStylesheets, + std::vector<std::string> JsScripts) + : ECtx(ECtx), PublicOnly(PublicOnly), OutDirectory(OutDirectory), + SourceRoot(SourceRoot), UserStylesheets(UserStylesheets), + JsScripts(JsScripts) { + if (!RepositoryUrl.empty()) { + this->RepositoryUrl = RepositoryUrl; + if (!RepositoryUrl.empty() && RepositoryUrl.find("http://") != 0 && + RepositoryUrl.find("https://") != 0) + this->RepositoryUrl->insert(0, "https://"); + } +} + } // namespace doc } // namespace clang Modified: clang-tools-extra/trunk/clang-doc/Representation.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.h?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Representation.h (original) +++ clang-tools-extra/trunk/clang-doc/Representation.h Fri Aug 9 10:49:41 2019 @@ -205,6 +205,9 @@ struct Location { 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) == @@ -220,8 +223,9 @@ struct Location { 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. @@ -375,14 +379,18 @@ mergeInfos(std::vector<std::unique_ptr<I struct ClangDocContext { ClangDocContext() = default; ClangDocContext(tooling::ExecutionContext *ECtx, bool PublicOnly, - StringRef OutDirectory, + StringRef OutDirectory, StringRef SourceRoot, + StringRef RepositoryUrl, std::vector<std::string> UserStylesheets, - std::vector<std::string> JsScripts) - : ECtx(ECtx), PublicOnly(PublicOnly), OutDirectory(OutDirectory), - UserStylesheets(UserStylesheets), JsScripts(JsScripts) {} + std::vector<std::string> JsScripts); tooling::ExecutionContext *ECtx; - bool PublicOnly; - std::string OutDirectory; + bool PublicOnly; // Indicates if only public declarations are documented. + std::string OutDirectory; // Directory for outputting generated files. + std::string SourceRoot; // Directory where processed files are stored. Links + // to definition locations will only be generated if + // the file is in this dir. + // URL of repository that hosts code used for links to definition locations. + llvm::Optional<std::string> RepositoryUrl; // Path of CSS stylesheets that will be copied to OutDirectory and used to // style all HTML files. std::vector<std::string> UserStylesheets; Modified: clang-tools-extra/trunk/clang-doc/Serialize.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Serialize.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Serialize.cpp (original) +++ clang-tools-extra/trunk/clang-doc/Serialize.cpp Fri Aug 9 10:49:41 2019 @@ -348,19 +348,21 @@ static void populateInfo(Info &I, const template <typename T> 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<EnumDecl>(T)) I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(), @@ -376,7 +378,7 @@ static void populateFunctionInfo(Functio std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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<NamespaceInfo>(); bool IsInAnonymousNamespace = false; populateInfo(*I, D, FC, IsInAnonymousNamespace); @@ -402,10 +404,11 @@ emitInfo(const NamespaceDecl *D, const F std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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<RecordInfo>(); 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 @@ emitInfo(const RecordDecl *D, const Full std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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 @@ emitInfo(const FunctionDecl *D, const Fu std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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 @@ emitInfo(const CXXMethodDecl *D, const F std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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 {}; Modified: clang-tools-extra/trunk/clang-doc/Serialize.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Serialize.h?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/Serialize.h (original) +++ clang-tools-extra/trunk/clang-doc/Serialize.h Fri Aug 9 10:49:41 2019 @@ -38,19 +38,19 @@ namespace serialize { // nullptr. std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber, - StringRef File, bool PublicOnly); + StringRef File, bool IsFileInRootDir, bool PublicOnly); std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>> 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 Modified: clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp (original) +++ clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp Fri Aug 9 10:49:41 2019 @@ -76,6 +76,18 @@ static llvm::cl::list<std::string> UserS llvm::cl::desc("CSS stylesheets to extend the default styles."), llvm::cl::cat(ClangDocCategory)); +static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"( +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<std::string> + RepositoryUrl("repository", llvm::cl::desc(R"( +URL of repository that hosts code. +Used for links to definition locations.)"), + llvm::cl::cat(ClangDocCategory)); + enum OutputFormatTy { md, yaml, @@ -142,7 +154,7 @@ bool CreateDirectory(const Twine &DirNam // <root>/A/B/C.<ext> // // namespace A { -// namesapce B { +// namespace B { // // class C {}; // @@ -191,10 +203,18 @@ int main(int argc, const char **argv) { tooling::ArgumentInsertPosition::END), ArgAdjuster); + llvm::SmallString<128> SourceRootDir; + // Check if the --source-root flag has a value + if (SourceRoot.empty()) + // If it's empty the current path is used as the default + llvm::sys::fs::current_path(SourceRootDir); + clang::doc::ClangDocContext CDCtx = { Exec->get()->getExecutionContext(), PublicOnly, OutDirectory, + SourceRootDir.str(), + RepositoryUrl, {UserStylesheets.begin(), UserStylesheets.end()}, {"index.js", "index_json.js"}}; Modified: clang-tools-extra/trunk/docs/clang-doc.rst URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-doc.rst?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/docs/clang-doc.rst (original) +++ clang-tools-extra/trunk/docs/clang-doc.rst Fri Aug 9 10:49:41 2019 @@ -66,7 +66,7 @@ Options .. code-block:: console - $ clang-doc --help + $ clang-doc --help USAGE: clang-doc [options] <source0> [... <sourceN>] OPTIONS: @@ -79,17 +79,27 @@ Options clang-doc options: - -doxygen - Use only doxygen-style comments to generate docs. - -dump - Dump intermediate results to bitcode file. - -extra-arg=<string> - Additional argument to append to the compiler command line - -extra-arg-before=<string> - Additional argument to prepend to the compiler command line - --format=<value> - Format for outputted docs. - =yaml - Documentation in YAML format. - =md - Documentation in MD format. - =html - Documentation in HTML format. - -output=<string> - Directory for outputting generated files. - -p=<string> - Build path - --public - Document only public declarations. - --stylesheets=<string> - CSS stylesheets to extend the default styles. - -``stylesheets`` should only be used if ``format`` is set to ``html``. + --doxygen - Use only doxygen-style comments to generate docs. + --extra-arg=<string> - Additional argument to append to the compiler command line + --extra-arg-before=<string> - Additional argument to prepend to the compiler command line + --format=<value> - Format for outputted docs. + =yaml - Documentation in YAML format. + =md - Documentation in MD format. + =html - Documentation in HTML format. + --ignore-map-errors - Continue if files are not mapped correctly. + --output=<string> - Directory for outputting generated files. + -p=<string> - Build path + --public - Document only public declarations. + --repository=<string> - + URL of repository that hosts code. + Used for links to definition locations. + --source-root=<string> - + Directory where processed files are stored. + Links to definition locations will only be + generated if the file is in this dir. + --stylesheets=<string> - CSS stylesheets to extend the default styles. + +The following flags shoud only be used if ``format`` is set to ``html``: +- ``repository`` +- ``source-root`` +- ``stylesheets`` Modified: clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp Fri Aug 9 10:49:41 2019 @@ -23,9 +23,9 @@ std::unique_ptr<Generator> getHTMLGenera } ClangDocContext -getClangDocContext(std::vector<std::string> UserStylesheets = {}) { - ClangDocContext CDCtx; - CDCtx.UserStylesheets = {UserStylesheets.begin(), UserStylesheets.end()}; +getClangDocContext(std::vector<std::string> UserStylesheets = {}, + StringRef RepositoryUrl = "") { + ClangDocContext CDCtx{{}, {}, {}, {}, RepositoryUrl, UserStylesheets, {}}; CDCtx.UserStylesheets.insert( CDCtx.UserStylesheets.begin(), "../share/clang/clang-doc-default-stylesheet.css"); @@ -127,7 +127,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) 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; @@ -147,7 +147,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext(); + ClangDocContext CDCtx = getClangDocContext({}, "http://www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw(<!DOCTYPE html> @@ -194,7 +194,12 @@ TEST(HTMLGeneratorTest, emitRecordHTML) </ul> <div> <h1>class r</h1> - <p>Defined at line 10 of test.cpp</p> + <p> + Defined at line + <a href="http://www.repository.com/dir/test.cpp#10">10</a> + of file + <a href="http://www.repository.com/dir/test.cpp">test.cpp</a> + </p> <p> Inherits from <a href="../../../path/to/F.html">F</a> @@ -232,7 +237,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML 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; @@ -246,7 +251,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML 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(<!DOCTYPE html> @@ -263,7 +268,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML <a href="path/to/int.html">int</a> P) </p> - <p>Defined at line 10 of test.cpp</p> + <p>Defined at line 10 of file dir/test.cpp</p> </div> )raw"; @@ -275,7 +280,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { I.Name = "e"; 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>{"test.cpp"}, true); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); I.Members.emplace_back("X"); @@ -285,7 +290,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext(); + ClangDocContext CDCtx = getClangDocContext({}, "www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw(<!DOCTYPE html> @@ -299,7 +304,12 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { <ul> <li>X</li> </ul> - <p>Defined at line 10 of test.cpp</p> + <p> + Defined at line + <a href="https://www.repository.com/test.cpp#10">10</a> + of file + <a href="https://www.repository.com/test.cpp">test.cpp</a> + </p> </div> )raw"; @@ -368,7 +378,7 @@ TEST(HTMLGeneratorTest, emitCommentHTML) <div> <h3 id="0000000000000000000000000000000000000000">f</h3> <p>void f(int I, int J)</p> - <p>Defined at line 10 of test.cpp</p> + <p>Defined at line 10 of file test.cpp</p> <div> <div> <p> Brief description.</p> Modified: clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp?rev=368460&r1=368459&r2=368460&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp (original) +++ clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp Fri Aug 9 10:49:41 2019 @@ -37,7 +37,7 @@ public: template <typename T> 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) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits