Mercurial > projects > dil
changeset 751:8caf18892c1b
Improved DDocEmitter and fixed bugs.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Mon, 11 Feb 2008 22:39:58 +0100 |
parents | 40a52ea29e3b |
children | 51e9dfe27f20 |
files | trunk/src/cmd/DDoc.d trunk/src/dil/ast/Declarations.d trunk/src/dil/doc/Doc.d trunk/src/dil/doc/Macro.d trunk/src/dil/doc/Parser.d trunk/src/dil/semantic/Pass1.d trunk/src/dil/semantic/Symbol.d |
diffstat | 7 files changed, 148 insertions(+), 57 deletions(-) [+] |
line wrap: on
line diff
--- a/trunk/src/cmd/DDoc.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/cmd/DDoc.d Mon Feb 11 22:39:58 2008 +0100 @@ -62,13 +62,16 @@ // Generate documentation. auto dest = new FilePath(destDir); dest.append(mod.getFQN() ~ ".html"); + InfoManager infoMan2; // Collects warnings from the macro expander. if (verbose) { Stdout.formatln("{} > {}", mod.filePath, dest); infoMan2 = new InfoManager(); } + writeDocFile(dest.toString(), mod, mtable, incUndoc, infoMan2); + if (infoMan2) infoMan ~= infoMan2.info; } @@ -96,7 +99,7 @@ mtable.insert("BODY", doc.text); // Do the macro expansion pass. auto fileText = MacroExpander.expand(mtable, "$(DDOC)", mod.filePath, infoMan); -// fileText ~= "\n<pre>\n" ~ doc.text ~ "\n</pre>"; +// fileText ~= "\n<pre>\n" ~ doc.text ~ "\n</pre>"; // Finally write the file out to the harddisk. auto file = new File(dest); file.write(fileText); @@ -161,20 +164,30 @@ /// Keeps track of previous comments in each scope. scope class Scope { - DDocComment old_prevCmnt; + DDocComment saved_prevCmnt; + bool saved_cmntIsDitto; + uint saved_prevDeclOffset; this() { // Save the previous comment of the parent scope. - old_prevCmnt = this.outer.prevCmnt; - // Entering a new scope. Set to null. + saved_prevCmnt = this.outer.prevCmnt; + saved_cmntIsDitto = this.outer.cmntIsDitto; + saved_prevDeclOffset = this.outer.prevDeclOffset; + // Entering a new scope. Clear variables. this.outer.prevCmnt = null; + this.outer.cmntIsDitto = false; + this.outer.prevDeclOffset = 0; } ~this() { // Restore the previous comment of the parent scope. - this.outer.prevCmnt = old_prevCmnt; + this.outer.prevCmnt = saved_prevCmnt; + this.outer.cmntIsDitto = saved_cmntIsDitto; + this.outer.prevDeclOffset = saved_prevDeclOffset; } } + bool cmntIsDitto; + DDocComment ddoc(Node node) { auto c = getDDocComment(node); @@ -182,9 +195,13 @@ if (c) { if (c.isDitto) + { this.cmnt = this.prevCmnt; + this.cmntIsDitto = true; + } else { + this.cmntIsDitto = false; this.cmnt = c; this.prevCmnt = c; } @@ -224,7 +241,7 @@ write("\n$(DDOC_PARAMS "); foreach (i, paramName; ps.paramNames) write("\n$(DDOC_PARAM_ROW ", - "$(DDOC_PARAM_ID ", paramName, ")", + "$(DDOC_PARAM_ID $(DDOC_PARAM ", paramName, "))", "$(DDOC_PARAM_DESC ", ps.paramDescs[i], ")", ")"); write(")"); @@ -281,7 +298,13 @@ { while (++p < end && *p != '>') // Skip to closing '>'. {} - p != end && p++; // Skip '>'. + if (p == end) + { // No closing '>' found. + p = begin + 1; + result ~= "<"; + continue; + } + p++; // Skip '>'. result ~= makeString(begin, p); } else @@ -289,8 +312,8 @@ continue; case '(': result ~= "("; break; case ')': result ~= ")"; break; - case '\'': result ~= "'"; break; // ' - case '"': result ~= """; break; + // case '\'': result ~= "'"; break; // ' + // case '"': result ~= """; break; case '>': result ~= ">"; break; case '&': if (p+1 < end && (isalpha(p[1]) || p[1] == '#')) @@ -300,15 +323,16 @@ case '-': if (p+2 < end && p[1] == '-' && p[2] == '-') { - p += 2; // Point to 3rd '-'. - auto codeBegin = p + 1; + while (p < end && *p == '-') + p++; + auto codeBegin = p; + p--; while (++p < end) if (p+2 < end && *p == '-' && p[1] == '-' && p[2] == '-') - { - result ~= "$(D_CODE " ~ scanCodeSection(makeString(codeBegin, p)) ~ ")"; - p += 3; break; - } + result ~= "$(D_CODE " ~ scanCodeSection(makeString(codeBegin, p)) ~ ")"; + while (p < end && *p == '-') + p++; continue; } //goto default; @@ -325,6 +349,26 @@ return text; } + /// Escapes '<', '>' and '&' with named HTML entities. + char[] escape(char[] text) + { + char[] result = new char[text.length]; // Reserve space. + result.length = 0; + foreach(c; text) + switch(c) + { + case '<': result ~= "<"; break; + case '>': result ~= ">"; break; + case '&': result ~= "&"; break; + default: result ~= c; + } + if (result.length != text.length) + return result; + // Nothing escaped. Return original text. + delete result; + return text; + } + void writeParams(Parameters params) { if (!params.items.length) @@ -340,12 +384,15 @@ assert(param.type); // Write storage classes. auto typeBegin = param.type.baseType.begin; - if (typeBegin !is param.begin) + if (typeBegin !is param.begin) // Write storage classes. write(textSpan(param.begin, typeBegin.prevNWS), " "); - write(textSpan(typeBegin, param.type.end)); - write(" $(DDOC_PARAM ", param.name.str, ")"); + write(escape(textSpan(typeBegin, param.type.end))); // Write type. + if (param.name) + write(" $(DDOC_PARAM ", param.name.str, ")"); if (param.isDVariadic) write("..."); + if (param.defValue) + write(" = ", escape(textSpan(param.defValue.begin, param.defValue.end))); } if (param !is lastParam) write(", "); @@ -357,7 +404,7 @@ { if (!isTemplatized) return; - write("(", (tparams ? textSpan(tparams.begin, tparams.end) : ""), ")"); + write("(", (tparams ? escape(textSpan(tparams.begin, tparams.end)) : ""), ")"); isTemplatized = false; tparams = null; } @@ -366,7 +413,10 @@ { if (bases.length == 0) return; - text ~= " : " ~ textSpan(bases[0].begin, bases[$-1].end); + auto basesBegin = bases[0].begin.prevNWS; + if (basesBegin.kind == TOK.Colon) + basesBegin = bases[0].begin; + text ~= " : " ~ escape(textSpan(basesBegin, bases[$-1].end)); } void writeFuncHeader(Declaration d, FuncBodyStatement s) @@ -384,22 +434,39 @@ text ~= s; } - void SYMBOL(char[][] strings...) + void SYMBOL(char[] name) { - write("$(DDOC_PSYMBOL "); - write(strings); - write(")"); + write("$(DDOC_PSYMBOL ", name, ")"); } - void DECL(void delegate() dg) + uint prevDeclOffset; + + void DECL(void delegate() dg, bool writeSemicolon = true) { + if (cmntIsDitto) + { alias prevDeclOffset offs; + assert(offs != 0); + auto savedText = text; + text = ""; + write("\n$(DDOC_DECL "); + dg(); + write(";)"); + // Insert text at offset. + auto len = text.length; + text = savedText[0..offs] ~ text ~ savedText[offs..$]; + offs += len; // Add length of the inserted text to the offset. + return; + } write("\n$(DDOC_DECL "); dg(); - write(")"); + write(writeSemicolon ? ";)" : ")"); + prevDeclOffset = text.length; } void DESC(void delegate() dg) { + if (cmntIsDitto) + return; write("\n$(DDOC_DECL_DD "); dg(); write(")"); @@ -416,7 +483,6 @@ { if (!ddoc(d)) return d; - scope s = new Scope(); DECL({ write(d.begin.srcText, " "); SYMBOL(d.name.str); @@ -426,6 +492,7 @@ DESC({ writeComment(); MEMBERS(is(T == ClassDeclaration) ? "CLASS" : "INTERFACE", { + scope s = new Scope(); d.decls && super.visit(d.decls); }); }); @@ -435,7 +502,6 @@ { if (!ddoc(d)) return d; - scope s = new Scope(); DECL({ write(d.begin.srcText, d.name ? " " : ""); if (d.name) @@ -445,6 +511,7 @@ DESC({ writeComment(); MEMBERS(is(T == StructDeclaration) ? "STRUCT" : "UNION", { + scope s = new Scope(); d.decls && super.visit(d.decls); }); }); @@ -460,7 +527,7 @@ { if (!ddoc(d)) return d; - DECL({ write(textSpan(d.begin, d.end)); }); + DECL({ write(textSpan(d.begin, d.end)); }, false); DESC({ writeComment(); }); return d; } @@ -469,7 +536,7 @@ { if (!ddoc(d)) return d; - DECL({ write(textSpan(d.begin, d.end)); }); + DECL({ write(textSpan(d.begin, d.end)); }, false); DESC({ writeComment(); }); return d; } @@ -478,14 +545,13 @@ { if (!ddoc(d)) return d; - scope s = new Scope(); DECL({ write("enum", d.name ? " " : ""); d.name && SYMBOL(d.name.str); }); DESC({ writeComment(); - MEMBERS("ENUM", { super.visit(d); }); + MEMBERS("ENUM", { scope s = new Scope(); super.visit(d); }); }); return d; } @@ -494,30 +560,29 @@ { if (!ddoc(d)) return d; - DECL({ SYMBOL(d.name.str); }); + DECL({ SYMBOL(d.name.str); }, false); DESC({ writeComment(); }); return d; } D visit(TemplateDeclaration d) { + this.isTemplatized = true; + this.tparams = d.tparams; if (d.begin.kind != TOK.Template) - { // This is a templatized class/interface/struct/union. - this.isTemplatized = true; - this.tparams = d.tparams; + // This is a templatized class/interface/struct/union. return super.visit(d.decls); - } if (!ddoc(d)) return d; - scope s = new Scope(); DECL({ write("template "); SYMBOL(d.name.str); - write(textSpan(d.begin.nextNWS.nextNWS, d.decls.begin.prevNWS)); + writeTemplateParams(); }); DESC({ writeComment(); MEMBERS("TEMPLATE", { + scope s = new Scope(); super.visit(d.decls); }); }); @@ -589,7 +654,14 @@ if (!ddoc(d)) return d; auto type = textSpan(d.returnType.baseType.begin, d.returnType.end); - DECL({ write(type, " "); SYMBOL(d.name.str); writeParams(d.params); }); + this.isTemplatized = d.isTemplatized(); + this.tparams = d.tparams; + DECL({ + write(escape(type), " "); + SYMBOL(d.name.str); + writeTemplateParams(); + writeParams(d.params); + }); DESC({ writeComment(); }); return d; } @@ -621,7 +693,7 @@ type = textSpan(d.typeNode.baseType.begin, d.typeNode.end); foreach (name; d.names) { - DECL({ write(type, " "); SYMBOL(name.str); }); + DECL({ write(escape(type), " "); SYMBOL(name.str); }); DESC({ writeComment(); }); } return d;
--- a/trunk/src/dil/ast/Declarations.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/ast/Declarations.d Mon Feb 11 22:39:58 2008 +0100 @@ -382,6 +382,12 @@ { this.linkageType = linkageType; } + + bool isTemplatized() + { // E.g.: void func(T)(T t) + // ^ params.begin.prevNWS + return params.begin.prevNWS.kind == TOK.RParen; + } } /// VariablesDeclaration := Type? Identifier ("=" Init)? ("," Identifier ("=" Init)?)* ";"
--- a/trunk/src/dil/doc/Doc.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/doc/Doc.d Mon Feb 11 22:39:58 2008 +0100 @@ -153,7 +153,7 @@ void scanSummaryAndDescription(char* p, char* end) { - assert(p < end); + assert(p <= end); char* sectionBegin = p; // Search for the end of the first paragraph. end--; // Decrement end, so we can look ahead one character.
--- a/trunk/src/dil/doc/Macro.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/doc/Macro.d Mon Feb 11 22:39:58 2008 +0100 @@ -227,7 +227,7 @@ break; // Add a new argument. args ~= makeString(argBegin, p); - while (++p < textEnd && isspace(*p)) + while (++p < textEnd && isspace(*p)) // Skip spaces. {} argBegin = p; continue; @@ -238,14 +238,15 @@ if (--level == 0) break MainLoop; break; - case '"', '\'': - auto c = *p; - while (++p < textEnd && *p != c) // Scan to next " or '. - {} - assert(*p == c || p == textEnd); - if (p == textEnd) - break MainLoop; - break; + // Commented out: causes too many problems in the expansion pass. + // case '"', '\'': + // auto c = *p; + // while (++p < textEnd && *p != c) // Scan to next " or '. + // {} + // assert(*p == c || p == textEnd); + // if (p == textEnd) + // break MainLoop; + // break; case '<': p++; if (p+2 < textEnd && *p == '!' && p[1] == '-' && p[2] == '-') // <!--
--- a/trunk/src/dil/doc/Parser.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/doc/Parser.d Mon Feb 11 22:39:58 2008 +0100 @@ -119,5 +119,6 @@ char[] makeString(char* begin, char* end) { + assert(begin <= end); return begin[0 .. end - begin]; }
--- a/trunk/src/dil/semantic/Pass1.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/semantic/Pass1.d Mon Feb 11 22:39:58 2008 +0100 @@ -73,15 +73,15 @@ } /// Insert a symbol into the current scope. - void insert(Symbol sym, Identifier* name) + void insert(Symbol symbol, Identifier* name) { - auto sym2 = scop.symbol.lookup(name); - if (sym2) - reportSymbolConflict(sym, sym2, name); + auto symX = scop.symbol.lookup(name); + if (symX) + reportSymbolConflict(symbol, symX, name); else - scop.symbol.insert(sym, name); + scop.symbol.insert(symbol, name); // Set the current scope symbol as the parent. - sym.parent = scop.symbol; + symbol.parent = scop.symbol; } /// Insert a symbol into scopeSym.
--- a/trunk/src/dil/semantic/Symbol.d Mon Feb 11 21:39:02 2008 +0100 +++ b/trunk/src/dil/semantic/Symbol.d Mon Feb 11 22:39:58 2008 +0100 @@ -83,4 +83,15 @@ mixin(isX!("Alias")); mixin(isX!("OverloadSet")); // mixin(isX!("Type")); + + /// Returns: the fully qualified name of this symbol. + /// E.g.: dil.semantic.Symbol.Symbol.getFQN + char[] getFQN() + { + if (!name) + return parent ? parent.getFQN() : ""; + if (parent) + return parent.getFQN() ~ '.' ~ name.str; + return name.str; + } }