From 3516ed5d688d3b64cdbe8ad8367d80725faf29a9 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 1 Oct 2016 15:47:42 +0200 Subject: [PATCH 1/2] Ddoc: wrap each symbol in the DDOC_MEMBER macro This allows better control of formatting of the output. For example, it allows to output an unordered list instead of a description list. By default it expands the first argument ($0) as is, basically making the macro disappear, to keep backwards compatibility. --- src/doc.d | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/doc.d b/src/doc.d index fd30deb8b525..f3e999bdf052 100644 --- a/src/doc.d +++ b/src/doc.d @@ -401,6 +401,7 @@ D_PSYMBOL = $(U $0) D_PARAM = $(I $0) DDOC_COMMENT = +DDOC_MEMBER = $0 DDOC_DECL = $(DT $(BIG $0)) DDOC_DECL_DD = $(DD $0) DDOC_DITTO = $(BR)$0 @@ -962,6 +963,7 @@ extern (C++) void emitComment(Dsymbol s, OutBuffer* buf, Scope* sc) // Put previous doc comment if exists if (DocComment* dc = sc.lastdc) { + buf.writestring("$(DDOC_MEMBER"); // Put the declaration signatures as the document 'title' buf.writestring(ddoc_decl_s); for (size_t i = 0; i < dc.a.dim; i++) @@ -995,6 +997,7 @@ extern (C++) void emitComment(Dsymbol s, OutBuffer* buf, Scope* sc) emitMemberComments(sds, buf, sc); } buf.writestring(ddoc_decl_dd_e); + buf.writeByte(')'); //printf("buf.2 = [[%.*s]]\n", buf->offset - o0, buf->data + o0); } if (s) From cab2c332903109f6afaf1075a535a91b187812c3 Mon Sep 17 00:00:00 2001 From: Jacob Carlborg Date: Sat, 1 Oct 2016 15:51:46 +0200 Subject: [PATCH 2/2] Ddoc: add new macros: DDOC_MEMBER_HEADER and DDOC_HEADER_ANCHOR The second parameter ($1) of the DDOC_HEADER_ANCHOR macro expands to the fully qualified name of the current symbol without the package and module prefix. That is, for a module level symbol it's the name of a symbol. For a nested symbol, like a method in a class, it's the symbol name prefixed with the class name. The third parameter ($2) expands to just the name of the current symbol. The DDOC_MEMBER_HEADER wraps DDOC_HEADER_ANCHOR to allow a sensible output format. The DDOC_MEMBER_HEADER is wrapped in the DDOC_MEMBER macro. By default these two macros expand to nothing, to keep backwards compatibility. --- src/doc.d | 76 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/doc.d b/src/doc.d index f3e999bdf052..ca7ce388f42f 100644 --- a/src/doc.d +++ b/src/doc.d @@ -402,6 +402,8 @@ D_PARAM = $(I $0) DDOC_COMMENT = DDOC_MEMBER = $0 +DDOC_MEMBER_HEADER = +DDOC_HEADER_ANCHOR = DDOC_DECL = $(DT $(BIG $0)) DDOC_DECL_DD = $(DD $0) DDOC_DITTO = $(BR)$0 @@ -753,18 +755,19 @@ extern (C++) static Scope* skipNonQualScopes(Scope* sc) return sc; } -extern (C++) static bool emitAnchorName(OutBuffer* buf, Dsymbol s, Scope* sc) +extern (C++) static bool emitAnchorName(OutBuffer* buf, Dsymbol s, Scope* sc, bool includeParent) { if (!s || s.isPackage() || s.isModule()) return false; // Add parent names first bool dot = false; - if (s.parent) - dot = emitAnchorName(buf, s.parent, sc); - else if (sc) - dot = emitAnchorName(buf, sc.scopesym, skipNonQualScopes(sc.enclosing)); + auto eponymousParent = getEponymousParent(s); + if (includeParent && s.parent || eponymousParent) + dot = emitAnchorName(buf, s.parent, sc, includeParent); + else if (includeParent && sc) + dot = emitAnchorName(buf, sc.scopesym, skipNonQualScopes(sc.enclosing), includeParent); // Eponymous template members can share the parent anchor name - if (getEponymousParent(s)) + if (eponymousParent) return dot; if (dot) buf.writeByte('.'); @@ -783,40 +786,59 @@ extern (C++) static bool emitAnchorName(OutBuffer* buf, Dsymbol s, Scope* sc) return true; } -extern (C++) static void emitAnchor(OutBuffer* buf, Dsymbol s, Scope* sc) +extern (C++) static void emitAnchor(OutBuffer* buf, Dsymbol s, Scope* sc, bool forHeader = false) { Identifier ident; { OutBuffer anc; - emitAnchorName(&anc, s, skipNonQualScopes(sc)); + emitAnchorName(&anc, s, skipNonQualScopes(sc), true); ident = Identifier.idPool(anc.peekSlice()); } auto pcount = cast(void*)ident in sc.anchorCounts; typeof(*pcount) count; - if (pcount) + if (!forHeader) { - // Existing anchor, - // don't write an anchor for matching consecutive ditto symbols - TemplateDeclaration td = getEponymousParent(s); - if (sc.prevAnchor == ident && sc.lastdc && (isDitto(s.comment) || (td && isDitto(td.comment)))) - return; + if (pcount) + { + // Existing anchor, + // don't write an anchor for matching consecutive ditto symbols + TemplateDeclaration td = getEponymousParent(s); + if (sc.prevAnchor == ident && sc.lastdc && (isDitto(s.comment) || (td && isDitto(td.comment)))) + return; - count = ++*pcount; - } - else - { - sc.anchorCounts[cast(void*)ident] = 1; - count = 1; + count = ++*pcount; + } + else + { + sc.anchorCounts[cast(void*)ident] = 1; + count = 1; + } } // cache anchor name sc.prevAnchor = ident; - buf.writestring("$(DDOC_ANCHOR "); - buf.writestring(ident.toChars()); + auto macroName = forHeader ? "DDOC_HEADER_ANCHOR" : "DDOC_ANCHOR"; + auto symbolName = ident.toString(); + buf.printf("$(%.*s %.*s", cast(int) macroName.length, macroName.ptr, + cast(int) symbolName.length, symbolName.ptr); // only append count once there's a duplicate if (count > 1) buf.printf(".%u", count); + + if (forHeader) + { + Identifier shortIdent; + { + OutBuffer anc; + emitAnchorName(&anc, s, skipNonQualScopes(sc), false); + shortIdent = Identifier.idPool(anc.peekSlice()); + } + + auto shortName = shortIdent.toString(); + buf.printf(", %.*s", cast(int) shortName.length, shortName.ptr); + } + buf.writeByte(')'); } @@ -963,7 +985,17 @@ extern (C++) void emitComment(Dsymbol s, OutBuffer* buf, Scope* sc) // Put previous doc comment if exists if (DocComment* dc = sc.lastdc) { + assert(dc.a.dim > 0, "Expects at least one declaration for a" ~ + "documentation comment"); + + auto symbol = dc.a[0]; + auto symbolName = symbol.ident.toString; + buf.writestring("$(DDOC_MEMBER"); + buf.writestring("$(DDOC_MEMBER_HEADER"); + emitAnchor(buf, symbol, sc, true); + buf.writeByte(')'); + // Put the declaration signatures as the document 'title' buf.writestring(ddoc_decl_s); for (size_t i = 0; i < dc.a.dim; i++)