1 let dumpTypes = options['dump-types'].split(',');
3 let interestingList = {};
6 function interestingType(t)
10 if (dumpTypes.some(function(n) n == name)) {
11 interestingList[name] = t;
16 for each (let base in t.bases) {
17 if (base.access == 'public' && interestingType(base.type)) {
26 function addSubtype(t, subt)
28 if (subt.typedef === undefined &&
29 subt.kind === undefined)
30 throw Error("Unexpected subtype: not class or typedef: " + subt);
32 if (t.subtypes === undefined)
35 t.subtypes.push(subt);
38 function process_type(t)
42 for each (let base in t.bases)
43 addSubtype(base.type, t);
46 function process_decl(d)
48 if (d.typedef !== undefined && d.memberOf)
49 addSubtype(d.memberOf, d);
52 function publicBases(t)
56 for each (let base in t.bases)
57 if (base.access == "public")
58 for each (let gbase in publicBases(base.type))
62 function publicMembers(t)
64 for each (let base in publicBases(t)) {
65 for each (let member in base.members) {
66 if (member.access === undefined)
67 throw Error("Harumph: member without access? " + member);
69 if (member.access != "public")
77 function signaturesMatch(m1, m2)
79 let p1 = m1.type.parameters;
80 let p2 = m2.type.parameters;
82 if (p1.length != p2.length)
85 for (let i = 0; i < p1.length; ++i)
93 * Get the short name of a decl name. E.g. turn
94 * "MyNamespace::MyClass::Method(int j) const" into
97 function getShortName(decl)
100 let lp = name.lastIndexOf('(');
102 name = name.slice(0, lp);
104 lp = name.lastIndexOf('::');
106 name = name.slice(lp + 2);
112 * Remove functions in a base class which were overridden in a derived
115 * Although really, we should perhaps do this the other way around, or even
116 * group the two together, but that can come later.
118 function removeOverrides(members)
120 let overrideMap = {};
121 for (let i = members.length - 1; i >= 0; --i) {
126 let shortName = getShortName(m);
128 let overrides = overrideMap[shortName];
129 if (overrides === undefined) {
130 overrideMap[shortName] = [m];
135 for each (let override in overrides) {
136 if (signaturesMatch(override, m)) {
137 // remove members[i], it was overridden
138 members.splice(i, 1);
150 * Generates the starting position of lines within a file.
152 function getLineLocations(fdata)
160 pos = fdata.indexOf('\n', pos) + 1;
170 * Find and return the doxygen comment immediately prior to the location
171 * object that was passed in.
173 * @todo: parse doccomment data such as @param, @returns
174 * @todo: parse comments for markup
176 function getDocComment(loc)
178 let fdata = read_file(loc.file);
179 let linemap = [l for (l in getLineLocations(fdata))];
181 if (loc.line >= linemap.length) {
182 warning("Location larger than actual header: " + loc);
186 let endpos = linemap[loc.line - 1] + loc.column - 1;
187 let semipos = fdata.lastIndexOf(';', endpos);
188 let bracepos = fdata.lastIndexOf('}', endpos);
189 let searchslice = fdata.slice(Math.max(semipos, bracepos) + 1, endpos);
191 let m = searchslice.match(/\/\*\*[\s\S]*?\*\//gm);
195 let dc = m[m.length - 1].slice(3, -2);
196 dc = dc.replace(/^\s*(\*+[ \t]*)?/gm, "");
198 return <pre class="doccomment">{dc}</pre>;
203 if (t.name !== undefined)
207 return "%s%s*".format(t.isConst ? "const " : "", typeName(t.type));
210 return "%s%s&".format(t.isConst ? "const " : "", typeName(t.type));
215 function publicBaseList(t)
218 for each (let b in t.bases) {
219 if (b.access == 'public')
220 l.* += <li><a href={"/en/%s".format(b.type.name)}>{b.type.name}</a></li>;
223 if (l.*.length() == 0)
227 <h2>Base Classes</h2>
233 * Get a source-link for a given location.
235 function getLocLink(loc, text)
237 return <a class="loc"
238 href={"http://hg.mozilla.org/mozilla-central/file/%s/[LOC%s]#l%i".format(options.rev, loc.file, loc.line)}>{text}</a>;
243 print("DUMP-TYPE(%s)".format(t.name));
245 let methodOverview = <tbody />;
246 let methodList = <div/>;
247 let memberList = <></>;
249 let shortNameMap = {};
251 let members = [m for (m in publicMembers(t))];
253 removeOverrides(members);
255 for each (let m in members) {
256 let qname = m.memberOf.name + '::';
258 // we don't inherit constructors from base classes
259 if (m.isConstructor && m.memberOf !== t)
262 if (m.name.indexOf(qname) != 0)
263 throw Error("Member name not qualified?");
265 let name = m.name.slice(qname.length);
267 if (name.indexOf('~') == 0)
273 let shortName = getShortName(m);
275 shortName = 'Constructors';
277 if (shortNameMap.hasOwnProperty(shortName)) {
278 innerList = shortNameMap[shortName];
283 <a href={'#%s'.format(escape(shortName))}>{shortName}</a>
287 methodOverview.insertChildAfter(null, overview);
289 methodOverview.appendChild(overview);
293 <h3 id={shortName}>{shortName}</h3>
299 methodList.insertChildAfter(null, shortMarkup);
301 methodList.appendChild(shortMarkup);
303 innerList = shortMarkup.dl;
304 shortNameMap[shortName] = innerList;
307 let parameters = <ul/>;
308 for each (p in m.parameters) {
313 if (/^D_\d+$/.test(name))
314 name = '<anonymous>';
316 parameters.* += <li>{typeName(p.type)} {name}</li>;
321 <dt id={name} class="methodName">
322 <code>{typeName(m.type.type)} {name}</code> - {getLocLink(m.loc, "source")}
325 {getDocComment(m.loc)}
326 {parameters.*.length() > 0 ?
335 memberList += <li class="member">{name}</li>;
341 <p>{getLocLink(t.loc, "Class Declaration")}</p>
343 {getDocComment(t.loc)}
345 {dumpTypes.some(function(n) n == t.name) ?
347 [MAP{t.name}-graph.map]
348 <img src={"/@api/deki/pages/=en%%252F%s/files/=%s-graph.png".format(t.name, t.name)} usemap="#classes" />
352 {methodOverview.*.length() > 0 ?
354 <h2>Method Overview</h2>
355 <table class="standard-table">{methodOverview}</table>
362 <h2>Data Members</h2>
364 {memberList.*.length() > 0 ?
366 <p><em>No public members.</em></p>
371 {methodList.*.length() > 0 ?
373 <p><em>No public methods.</em></p>
378 write_file(t.name + ".html", r.toXMLString());
381 function graphType(t)
383 print("GRAPH-TYPE(%s)".format(t.name));
385 let contents = "digraph classes {\n"
386 + " node [shape=rectangle fontsize=11]\n"
387 + " %s;\n".format(t.name);
389 function graphClass(c)
391 contents += '%s [URL="http://developer.mozilla.org/en/%s"]\n'.format(c.name, c.name);
393 for each (let st in c.subtypes) {
394 contents += " %s -> %s;\n".format(c.name, st.name);
403 write_file(t.name + "-graph.gv", contents);
408 for (let p in typelist)
409 dumpType(typelist[p]);
411 for (let n in interestingList)
412 graphType(interestingList[n]);