https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/174914
>From 085d7a3311937873fe7d4fed9aaf271d10f91e58 Mon Sep 17 00:00:00 2001 From: Erick Velez <[email protected]> Date: Fri, 2 Jan 2026 16:19:17 -0800 Subject: [PATCH] add line prefix from CDCtx, fix extra tag --- clang-tools-extra/clang-doc/JSONGenerator.cpp | 119 +++++++++++------- .../clang-doc/assets/alias-template.mustache | 2 +- .../clang-doc/assets/class-template.mustache | 4 +- .../clang-doc/assets/enum-template.mustache | 4 +- .../assets/function-template.mustache | 2 +- .../assets/namespace-template.mustache | 4 +- clang-tools-extra/test/clang-doc/enum.cpp | 10 +- .../test/clang-doc/mustache-index.cpp | 4 +- .../test/clang-doc/templates.cpp | 3 +- 9 files changed, 88 insertions(+), 64 deletions(-) diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index ad76c40d49db8..12d439c6acbe4 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -25,7 +25,8 @@ const char *JSONGenerator::Format = "json"; static void serializeInfo(const ConstraintInfo &I, Object &Obj); static void serializeInfo(const RecordInfo &I, Object &Obj, - const std::optional<StringRef> &RepositoryUrl); + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLinePrefix); static void serializeReference(const Reference &Ref, Object &ReferenceObj); @@ -75,7 +76,8 @@ static std::string infoTypeToString(InfoType IT) { static json::Object serializeLocation(const Location &Loc, - const std::optional<StringRef> RepositoryUrl) { + const std::optional<StringRef> RepositoryUrl, + const std::optional<StringRef> RepositoryLinePrefix) { Object LocationObj = Object(); LocationObj["LineNumber"] = Loc.StartLineNumber; LocationObj["Filename"] = Loc.Filename; @@ -84,7 +86,14 @@ serializeLocation(const Location &Loc, return LocationObj; SmallString<128> FileURL(*RepositoryUrl); sys::path::append(FileURL, sys::path::Style::posix, Loc.Filename); - FileURL += "#" + std::to_string(Loc.StartLineNumber); + + std::string LinePrefix; + if (!RepositoryLinePrefix) + LinePrefix = "#L"; + else + LinePrefix = *RepositoryLinePrefix; + + FileURL += LinePrefix + std::to_string(Loc.StartLineNumber); LocationObj["FileURL"] = FileURL; return LocationObj; } @@ -338,7 +347,8 @@ static void generateContext(const Info &I, Object &Obj) { static void serializeCommonAttributes(const Info &I, json::Object &Obj, - const std::optional<StringRef> RepositoryUrl) { + const std::optional<StringRef> RepositoryUrl, + const std::optional<StringRef> RepositoryLinePrefix) { insertNonEmpty("Name", I.Name, Obj); Obj["USR"] = toHex(toStringRef(I.USR)); Obj["InfoType"] = infoTypeToString(I.IT); @@ -378,8 +388,8 @@ serializeCommonAttributes(const Info &I, json::Object &Obj, if (I.IT != InfoType::IT_namespace) { const auto *Symbol = static_cast<const SymbolInfo *>(&I); if (Symbol->DefLoc) - Obj["Location"] = - serializeLocation(Symbol->DefLoc.value(), RepositoryUrl); + Obj["Location"] = serializeLocation(Symbol->DefLoc.value(), RepositoryUrl, + RepositoryLinePrefix); } if (!I.Contexts.empty()) @@ -405,11 +415,12 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) { // differently. Only enums, records, and typedefs are handled here. static void serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj, - const std::optional<StringRef> RepositoryUrl) { - static auto SerializeInfo = [RepositoryUrl](const auto &Info, - Object &Object) { - serializeInfo(Info, Object, RepositoryUrl); - }; + const std::optional<StringRef> RepositoryUrl, + const std::optional<StringRef> RepositoryLinePrefix) { + static auto SerializeInfo = + [RepositoryUrl, RepositoryLinePrefix](const auto &Info, Object &Object) { + serializeInfo(Info, Object, RepositoryUrl, RepositoryLinePrefix); + }; if (!Children.Enums.empty()) { serializeArray(Children.Enums, Obj, "Enums", SerializeInfo); @@ -492,8 +503,9 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) { } static void serializeInfo(const ConceptInfo &I, Object &Obj, - const std::optional<StringRef> &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLine) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLine); Obj["IsType"] = I.IsType; Obj["ConstraintExpression"] = I.ConstraintExpression; serializeInfo(I.Template, Obj); @@ -517,8 +529,9 @@ static void serializeInfo(const FieldTypeInfo &I, Object &Obj) { } static void serializeInfo(const FunctionInfo &F, json::Object &Obj, - const std::optional<StringRef> RepositoryURL) { - serializeCommonAttributes(F, Obj, RepositoryURL); + const std::optional<StringRef> RepositoryURL, + const std::optional<StringRef> RepositoryLine) { + serializeCommonAttributes(F, Obj, RepositoryURL, RepositoryLine); Obj["IsStatic"] = F.IsStatic; auto ReturnTypeObj = Object(); @@ -541,8 +554,9 @@ static void serializeInfo(const EnumValueInfo &I, Object &Obj) { } static void serializeInfo(const EnumInfo &I, json::Object &Obj, - const std::optional<StringRef> &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLine) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLine); Obj["Scoped"] = I.Scoped; if (I.BaseType) { @@ -558,9 +572,11 @@ static void serializeInfo(const EnumInfo &I, json::Object &Obj, serializeArray(I.Members, Obj, "Members", SerializeInfoLambda); } -static void serializeInfo(const TypedefInfo &I, json::Object &Obj, - const std::optional<StringRef> &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const TypedefInfo &I, json::Object &Obj, + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); Obj["TypeDeclaration"] = I.TypeDeclaration; Obj["IsUsing"] = I.IsUsing; json::Value TypeVal = Object(); @@ -571,9 +587,12 @@ static void serializeInfo(const TypedefInfo &I, json::Object &Obj, serializeInfo(I.Template.value(), Obj); } -static void serializeInfo(const BaseRecordInfo &I, Object &Obj, - const std::optional<StringRef> &RepositoryUrl) { - serializeInfo(static_cast<const RecordInfo &>(I), Obj, RepositoryUrl); +static void +serializeInfo(const BaseRecordInfo &I, Object &Obj, + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLinePrefix) { + serializeInfo(static_cast<const RecordInfo &>(I), Obj, RepositoryUrl, + RepositoryLinePrefix); Obj["IsVirtual"] = I.IsVirtual; Obj["Access"] = getAccessSpelling(I.Access); Obj["IsParent"] = I.IsParent; @@ -593,7 +612,7 @@ static void serializeInfo(const FriendInfo &I, Object &Obj) { serializeInfo(I.ReturnType.value(), ReturnTypeObj); Obj["ReturnType"] = std::move(ReturnTypeObj); } - serializeCommonAttributes(I, Obj, std::nullopt); + serializeCommonAttributes(I, Obj, std::nullopt, std::nullopt); } static void insertArray(Object &Obj, json::Value &Array, StringRef Key) { @@ -601,9 +620,11 @@ static void insertArray(Object &Obj, json::Value &Array, StringRef Key) { Obj["Has" + Key.str()] = true; } -static void serializeInfo(const RecordInfo &I, json::Object &Obj, - const std::optional<StringRef> &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const RecordInfo &I, json::Object &Obj, + const std::optional<StringRef> &RepositoryUrl, + const std::optional<StringRef> &RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); Obj["TagType"] = getTagType(I.TagType); Obj["IsTypedef"] = I.IsTypeDef; Obj["MangledName"] = I.MangledName; @@ -617,7 +638,7 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, for (const auto &Function : I.Children.Functions) { json::Value FunctionVal = Object(); auto &FunctionObj = *FunctionVal.getAsObject(); - serializeInfo(Function, FunctionObj, RepositoryUrl); + serializeInfo(Function, FunctionObj, RepositoryUrl, RepositoryLinePrefix); AccessSpecifier Access = Function.Access; if (Access == AccessSpecifier::AS_public) PubFunctionsArrayRef.push_back(FunctionVal); @@ -663,11 +684,12 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, } if (!I.Bases.empty()) - serializeArray( - I.Bases, Obj, "Bases", - [&RepositoryUrl](const BaseRecordInfo &Base, Object &BaseObj) { - serializeInfo(Base, BaseObj, RepositoryUrl); - }); + serializeArray(I.Bases, Obj, "Bases", + [&RepositoryUrl, &RepositoryLinePrefix]( + const BaseRecordInfo &Base, Object &BaseObj) { + serializeInfo(Base, BaseObj, RepositoryUrl, + RepositoryLinePrefix); + }); if (!I.Parents.empty()) { serializeArray(I.Parents, Obj, "Parents", SerializeReferenceLambda); @@ -688,12 +710,14 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, Obj["HasFriends"] = true; } - serializeCommonChildren(I.Children, Obj, RepositoryUrl); + serializeCommonChildren(I.Children, Obj, RepositoryUrl, RepositoryLinePrefix); } -static void serializeInfo(const VarInfo &I, json::Object &Obj, - const std::optional<StringRef> RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const VarInfo &I, json::Object &Obj, + const std::optional<StringRef> RepositoryUrl, + const std::optional<StringRef> RepositoryUrlLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryUrlLinePrefix); Obj["IsStatic"] = I.IsStatic; auto TypeObj = Object(); serializeInfo(I.Type, TypeObj); @@ -701,8 +725,9 @@ static void serializeInfo(const VarInfo &I, json::Object &Obj, } static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, - const std::optional<StringRef> RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional<StringRef> RepositoryUrl, + const std::optional<StringRef> RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); if (I.USR == GlobalNamespaceID) Obj["Name"] = "Global Namespace"; @@ -712,10 +737,10 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, Obj["HasNamespaces"] = true; } - static auto SerializeInfo = [RepositoryUrl](const auto &Info, - Object &Object) { - serializeInfo(Info, Object, RepositoryUrl); - }; + static auto SerializeInfo = + [RepositoryUrl, RepositoryLinePrefix](const auto &Info, Object &Object) { + serializeInfo(Info, Object, RepositoryUrl, RepositoryLinePrefix); + }; if (!I.Children.Functions.empty()) { serializeArray(I.Children.Functions, Obj, "Functions", SerializeInfo); @@ -730,7 +755,7 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, if (!I.Children.Variables.empty()) serializeArray(I.Children.Variables, Obj, "Variables", SerializeInfo); - serializeCommonChildren(I.Children, Obj, RepositoryUrl); + serializeCommonChildren(I.Children, Obj, RepositoryUrl, RepositoryLinePrefix); } static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) { @@ -864,10 +889,12 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS, switch (I->IT) { case InfoType::IT_namespace: - serializeInfo(*static_cast<NamespaceInfo *>(I), Obj, CDCtx.RepositoryUrl); + serializeInfo(*static_cast<NamespaceInfo *>(I), Obj, CDCtx.RepositoryUrl, + CDCtx.RepositoryLinePrefix); break; case InfoType::IT_record: - serializeInfo(*static_cast<RecordInfo *>(I), Obj, CDCtx.RepositoryUrl); + serializeInfo(*static_cast<RecordInfo *>(I), Obj, CDCtx.RepositoryUrl, + CDCtx.RepositoryLinePrefix); break; case InfoType::IT_concept: case InfoType::IT_enum: diff --git a/clang-tools-extra/clang-doc/assets/alias-template.mustache b/clang-tools-extra/clang-doc/assets/alias-template.mustache index 9b32f132e9ef3..835d9aab1417e 100644 --- a/clang-tools-extra/clang-doc/assets/alias-template.mustache +++ b/clang-tools-extra/clang-doc/assets/alias-template.mustache @@ -7,6 +7,6 @@ {{>Comments}} {{/Description}} {{#Location}} - <p>Defined at line {{LineNumber}} of file {{Filename}}</p> + <p>Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}<a href="{{FileURL}}">{{Filename}}</a>{{/FileURL}}</p> {{/Location}} </div> diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache index ef5a7572a3f48..71ed1abd1016d 100644 --- a/clang-tools-extra/clang-doc/assets/class-template.mustache +++ b/clang-tools-extra/clang-doc/assets/class-template.mustache @@ -153,7 +153,9 @@ {{/Template}} <div class="hero__title"> <h1 class="hero__title-large">{{TagType}} {{Name}}</h1> - <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p> + {{#Location}} + <p>Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}<a href="{{FileURL}}">{{Filename}}</a>{{/FileURL}}</p> + {{/Location}} {{#Description}} <div class="doc-card"> {{>Comments}} diff --git a/clang-tools-extra/clang-doc/assets/enum-template.mustache b/clang-tools-extra/clang-doc/assets/enum-template.mustache index af1364c4d37f6..22661c69f9c22 100644 --- a/clang-tools-extra/clang-doc/assets/enum-template.mustache +++ b/clang-tools-extra/clang-doc/assets/enum-template.mustache @@ -42,8 +42,6 @@ </div> {{/EnumComments}} {{#Location}} - <div> - Defined at line {{LineNumber}} of file {{Filename}} - </div> + <p>Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}<a href="{{FileURL}}">{{Filename}}</a>{{/FileURL}}</p> {{/Location}} </div> diff --git a/clang-tools-extra/clang-doc/assets/function-template.mustache b/clang-tools-extra/clang-doc/assets/function-template.mustache index 354e26b7b05b0..510219a63d379 100644 --- a/clang-tools-extra/clang-doc/assets/function-template.mustache +++ b/clang-tools-extra/clang-doc/assets/function-template.mustache @@ -18,6 +18,6 @@ </div> {{/Description}} {{#Location}} - <p>Defined at line {{LineNumber}} of file {{Filename}}</p> + <p>Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}<a href="{{FileURL}}">{{Filename}}</a>{{/FileURL}}</p> {{/Location}} </div> diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache index 567af626714ef..fc0b9e2c388d9 100644 --- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache +++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache @@ -176,7 +176,9 @@ {{#Description}} {{>Comments}} {{/Description}} - <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p> + {{#Location}} + <p>Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}<a href="{{FileURL}}">{{Filename}}</a>{{/FileURL}}</p> + {{/Location}} </div> {{/Concepts}} </section> diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp index ce844ec072564..f10d8808f185e 100644 --- a/clang-tools-extra/test/clang-doc/enum.cpp +++ b/clang-tools-extra/test/clang-doc/enum.cpp @@ -21,7 +21,7 @@ */ enum Color { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> Red, ///< Comment 1 Green, ///< Comment 2 Blue ///< Comment 3 @@ -64,7 +64,7 @@ enum Color { */ enum class Shapes { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> /// Comment 1 Circle, @@ -115,7 +115,7 @@ class Animals { */ enum AnimalType { // MD-ANIMAL-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-ANIMAL-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-ANIMAL-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> Dog, ///< Man's best friend Cat, ///< Man's other best friend Iguana ///< A lizard @@ -148,9 +148,7 @@ class Animals { // HTML-ANIMAL-NEXT: </tr> // HTML-ANIMAL-NEXT: </tbody> // HTML-ANIMAL-NEXT: </table> -// HTML-ANIMAL-NEXT: <div> -// HTML-ANIMAL-NEXT: Defined at line 116 of file {{.*}}enum.cpp -// HTML-ANIMAL-NEXT: </div> +// HTML-ANIMAL-NEXT: <p>Defined at line 116 of file {{.*}}enum.cpp</p> // HTML-ANIMAL-NEXT: </div> // HTML-ANIMAL-NEXT: </section> diff --git a/clang-tools-extra/test/clang-doc/mustache-index.cpp b/clang-tools-extra/test/clang-doc/mustache-index.cpp index 9706307287f9b..caaa932d3e02f 100644 --- a/clang-tools-extra/test/clang-doc/mustache-index.cpp +++ b/clang-tools-extra/test/clang-doc/mustache-index.cpp @@ -54,9 +54,7 @@ class Foo; // CHECK-NEXT: </tr> // CHECK-NEXT: </tbody> // CHECK-NEXT: </table> -// CHECK-NEXT: <div> -// CHECK-NEXT: Defined at line 5 of file {{.*}}mustache-index.cpp -// CHECK-NEXT: </div> +// CHECK-NEXT: <p>Defined at line 5 of file {{.*}}mustache-index.cpp</p> // CHECK-NEXT: </div> // CHECK-NEXT: </div> // CHECK-NEXT: </section> diff --git a/clang-tools-extra/test/clang-doc/templates.cpp b/clang-tools-extra/test/clang-doc/templates.cpp index 27fff6ed5a09d..8c9b0b53a8b3d 100644 --- a/clang-tools-extra/test/clang-doc/templates.cpp +++ b/clang-tools-extra/test/clang-doc/templates.cpp @@ -78,8 +78,7 @@ void ParamPackFunction(T... args); // JSON-NEXT: }, // HTML: <pre><code class="language-cpp code-clang-doc">template <class... T></code></pre> -// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">void ParamPackFunction (T... args)</code></pre> -// HTML-NEXT: </div> +// HTML-NEXT: <pre><code class="language-cpp code-clang-doc">void ParamPackFunction (T... args)</code></pre> template <typename T, int U = 1> void function(T x) {} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
