let dumpTypes = options['dump-types'].split(','); function interestingType(name) dumpTypes.some(function(n) n == name); let typelist = {}; function addSubtype(t, subt) { if (subt.typedef === undefined && subt.kind === undefined) throw Error("Unexpected subtype: not class or typedef: " + subt); if (t.subtypes === undefined) t.subtypes = []; t.subtypes.push(subt); } function process_type(t) { let name = t.name; if (interestingType(t.name)) typelist[t.name] = t; if (t.memberOf) addSubtype(t.memberOf, t); } function process_decl(d) { if (d.typedef !== undefined && d.memberOf) addSubtype(d.memberOf, d); } function publicBases(t) { yield t; for each (let base in t.bases) if (base.access == "public") for each (let gbase in publicBases(base.type)) yield gbase; } function publicMembers(t) { for each (let base in publicBases(t)) { for each (let member in base.members) { if (member.access === undefined) throw Error("Harumph: member without access? " + member); if (member.access != "public") continue; yield member; } } } function signaturesMatch(m1, m2) { let p1 = m1.type.parameters; let p2 = m2.type.parameters; if (p1.length != p2.length) return false; for (let i = 0; i < p1.length; ++i) if (p1[i] !== p2[i]) return false; return true; } /** * Get the short name of a decl name. E.g. turn * "MyNamespace::MyClass::Method(int j) const" into * "Method" */ function getShortName(decl) { let name = decl.name; let lp = name.lastIndexOf('('); if (lp != -1) name = name.slice(0, lp); lp = name.lastIndexOf('::'); if (lp != -1) name = name.slice(lp + 2); return name; } /** * Remove functions in a base class which were overridden in a derived * class. * * Although really, we should perhaps do this the other way around, or even * group the two together, but that can come later. */ function removeOverrides(members) { let overrideMap = {}; for (let i = members.length - 1; i >= 0; --i) { let m = members[i]; if (!m.isFunction) continue; let shortName = getShortName(m); let overrides = overrideMap[shortName]; if (overrides === undefined) { overrideMap[shortName] = [m]; continue; } let found = false; for each (let override in overrides) { if (signaturesMatch(override, m)) { // remove members[i], it was overridden members.splice(i, 1); found = true; } } if (found) continue; overrides.push(m); } } /** * Generates the starting position of lines within a file. */ function getLineLocations(fdata) { yield 0; let r = /\n/y; let pos = 0; let i = 1; for (;;) { pos = fdata.indexOf('\n', pos) + 1; if (pos == 0) break; yield pos; i++; } } /** * Find and return the doxygen comment immediately prior to the location * object that was passed in. * * @todo: parse doccomment data such as @param, @returns * @todo: parse comments for markup */ function getDocComment(loc) { let fdata = read_file(loc.file); let linemap = [l for (l in getLineLocations(fdata))]; if (loc.line >= linemap.length) { warning("Location larger than actual header: " + loc); return <>; } let endpos = linemap[loc.line - 1] + loc.column - 1; let semipos = fdata.lastIndexOf(';', endpos); let bracepos = fdata.lastIndexOf('}', endpos); let searchslice = fdata.slice(Math.max(semipos, bracepos) + 1, endpos); let m = searchslice.match(/\/\*\*[\s\S]*?\*\//gm); if (m === null) return <>; let dc = m[m.length - 1].slice(3, -2); dc = dc.replace(/^\s*(\*+[ \t]*)?/gm, ""); return
{dc}
; } function typeName(t) { if (t.name !== undefined) return t.name; if (t.isPointer) return "%s%s*".format(t.isConst ? "const " : "", typeName(t.type)); if (t.isReference) return "%s%s&".format(t.isConst ? "const " : "", typeName(t.type)); return t.toString(); } function publicBaseList(t) { let l =