diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index ad76c40d49db8..ec234db19ed1a 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -8,6 +8,9 @@ using namespace llvm::json; namespace clang { namespace doc { +// FIXME: These static methods should be refactored into methods for +// `JSONGenerator`. It's cumbersome to pass around important properties from +// ClangDocContext using these static methods. class JSONGenerator : public Generator { public: static const char *Format; @@ -25,7 +28,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 &RepositoryUrl); + const std::optional &RepositoryUrl, + const std::optional &RepositoryLinePrefix); static void serializeReference(const Reference &Ref, Object &ReferenceObj); @@ -75,7 +79,8 @@ static std::string infoTypeToString(InfoType IT) { static json::Object serializeLocation(const Location &Loc, - const std::optional RepositoryUrl) { + const std::optional RepositoryUrl, + const std::optional RepositoryLinePrefix) { Object LocationObj = Object(); LocationObj["LineNumber"] = Loc.StartLineNumber; LocationObj["Filename"] = Loc.Filename; @@ -84,7 +89,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 +350,8 @@ static void generateContext(const Info &I, Object &Obj) { static void serializeCommonAttributes(const Info &I, json::Object &Obj, - const std::optional RepositoryUrl) { + const std::optional RepositoryUrl, + const std::optional RepositoryLinePrefix) { insertNonEmpty("Name", I.Name, Obj); Obj["USR"] = toHex(toStringRef(I.USR)); Obj["InfoType"] = infoTypeToString(I.IT); @@ -378,8 +391,8 @@ serializeCommonAttributes(const Info &I, json::Object &Obj, if (I.IT != InfoType::IT_namespace) { const auto *Symbol = static_cast(&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 +418,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 RepositoryUrl) { - static auto SerializeInfo = [RepositoryUrl](const auto &Info, - Object &Object) { - serializeInfo(Info, Object, RepositoryUrl); - }; + const std::optional RepositoryUrl, + const std::optional 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 +506,9 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) { } static void serializeInfo(const ConceptInfo &I, Object &Obj, - const std::optional &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional &RepositoryUrl, + const std::optional &RepositoryLine) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLine); Obj["IsType"] = I.IsType; Obj["ConstraintExpression"] = I.ConstraintExpression; serializeInfo(I.Template, Obj); @@ -517,8 +532,9 @@ static void serializeInfo(const FieldTypeInfo &I, Object &Obj) { } static void serializeInfo(const FunctionInfo &F, json::Object &Obj, - const std::optional RepositoryURL) { - serializeCommonAttributes(F, Obj, RepositoryURL); + const std::optional RepositoryURL, + const std::optional RepositoryLine) { + serializeCommonAttributes(F, Obj, RepositoryURL, RepositoryLine); Obj["IsStatic"] = F.IsStatic; auto ReturnTypeObj = Object(); @@ -541,8 +557,9 @@ static void serializeInfo(const EnumValueInfo &I, Object &Obj) { } static void serializeInfo(const EnumInfo &I, json::Object &Obj, - const std::optional &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional &RepositoryUrl, + const std::optional &RepositoryLine) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLine); Obj["Scoped"] = I.Scoped; if (I.BaseType) { @@ -558,9 +575,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 &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const TypedefInfo &I, json::Object &Obj, + const std::optional &RepositoryUrl, + const std::optional &RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); Obj["TypeDeclaration"] = I.TypeDeclaration; Obj["IsUsing"] = I.IsUsing; json::Value TypeVal = Object(); @@ -571,9 +590,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 &RepositoryUrl) { - serializeInfo(static_cast(I), Obj, RepositoryUrl); +static void +serializeInfo(const BaseRecordInfo &I, Object &Obj, + const std::optional &RepositoryUrl, + const std::optional &RepositoryLinePrefix) { + serializeInfo(static_cast(I), Obj, RepositoryUrl, + RepositoryLinePrefix); Obj["IsVirtual"] = I.IsVirtual; Obj["Access"] = getAccessSpelling(I.Access); Obj["IsParent"] = I.IsParent; @@ -593,7 +615,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 +623,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 &RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const RecordInfo &I, json::Object &Obj, + const std::optional &RepositoryUrl, + const std::optional &RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); Obj["TagType"] = getTagType(I.TagType); Obj["IsTypedef"] = I.IsTypeDef; Obj["MangledName"] = I.MangledName; @@ -617,7 +641,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 +687,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 +713,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 RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); +static void +serializeInfo(const VarInfo &I, json::Object &Obj, + const std::optional RepositoryUrl, + const std::optional RepositoryUrlLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryUrlLinePrefix); Obj["IsStatic"] = I.IsStatic; auto TypeObj = Object(); serializeInfo(I.Type, TypeObj); @@ -701,8 +728,9 @@ static void serializeInfo(const VarInfo &I, json::Object &Obj, } static void serializeInfo(const NamespaceInfo &I, json::Object &Obj, - const std::optional RepositoryUrl) { - serializeCommonAttributes(I, Obj, RepositoryUrl); + const std::optional RepositoryUrl, + const std::optional RepositoryLinePrefix) { + serializeCommonAttributes(I, Obj, RepositoryUrl, RepositoryLinePrefix); if (I.USR == GlobalNamespaceID) Obj["Name"] = "Global Namespace"; @@ -712,10 +740,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 +758,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 +892,12 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS, switch (I->IT) { case InfoType::IT_namespace: - serializeInfo(*static_cast(I), Obj, CDCtx.RepositoryUrl); + serializeInfo(*static_cast(I), Obj, CDCtx.RepositoryUrl, + CDCtx.RepositoryLinePrefix); break; case InfoType::IT_record: - serializeInfo(*static_cast(I), Obj, CDCtx.RepositoryUrl); + serializeInfo(*static_cast(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}} -

Defined at line {{LineNumber}} of file {{Filename}}

+

Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}{{Filename}}{{/FileURL}}

{{/Location}} diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache index 979a486816059..9631accc80287 100644 --- a/clang-tools-extra/clang-doc/assets/class-template.mustache +++ b/clang-tools-extra/clang-doc/assets/class-template.mustache @@ -155,7 +155,9 @@ {{/Template}}

{{TagType}} {{Name}}

-

Defined at line {{Location.LineNumber}} of file {{Location.Filename}}

+ {{#Location}} +

Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}{{Filename}}{{/FileURL}}

+ {{/Location}} {{#Description}}
{{>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 @@
{{/EnumComments}} {{#Location}} -
- Defined at line {{LineNumber}} of file {{Filename}} -
+

Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}{{Filename}}{{/FileURL}}

{{/Location}}
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 @@ {{/Description}} {{#Location}} -

Defined at line {{LineNumber}} of file {{Filename}}

+

Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}{{Filename}}{{/FileURL}}

{{/Location}} diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache index f3f324568031f..04c31fb140962 100644 --- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache +++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache @@ -178,7 +178,9 @@ {{#Description}} {{>Comments}} {{/Description}} -

Defined at line {{Location.LineNumber}} of file {{Location.Filename}}

+ {{#Location}} +

Defined at line {{LineNumber}} of file {{^FileURL}}{{Filename}}{{/FileURL}}{{#FileURL}}{{Filename}}{{/FileURL}}

+ {{/Location}} {{/Concepts}} 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:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

+ // HTML-INDEX-LINE:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

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:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

+ // HTML-INDEX-LINE:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

/// 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:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

+ // HTML-ANIMAL-LINE:

Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp

Dog, ///< Man's best friend Cat, ///< Man's other best friend Iguana ///< A lizard @@ -148,9 +148,7 @@ class Animals { // HTML-ANIMAL-NEXT: // HTML-ANIMAL-NEXT: // HTML-ANIMAL-NEXT: -// HTML-ANIMAL-NEXT:
-// HTML-ANIMAL-NEXT: Defined at line 116 of file {{.*}}enum.cpp -// HTML-ANIMAL-NEXT:
+// HTML-ANIMAL-NEXT:

Defined at line 116 of file {{.*}}enum.cpp

// HTML-ANIMAL-NEXT: // HTML-ANIMAL-NEXT: 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: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT:
-// CHECK-NEXT: Defined at line 5 of file {{.*}}mustache-index.cpp -// CHECK-NEXT:
+// CHECK-NEXT:

Defined at line 5 of file {{.*}}mustache-index.cpp

// CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: 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:
template <class... T>
-// HTML-NEXT:
void ParamPackFunction (T... args)
-// HTML-NEXT: +// HTML-NEXT:
void ParamPackFunction (T... args)
template void function(T x) {}