michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * graph-frameclasses.js: a dehydra script to collect information about michael@0: * the class hierarchy of frame types. michael@0: */ michael@0: michael@0: function inheritsFrom(t, baseName) michael@0: { michael@0: let name = t.name; michael@0: if (name == baseName) michael@0: return true; michael@0: michael@0: for each (let base in t.bases) michael@0: if (inheritsFrom(base.type, baseName)) michael@0: return true; michael@0: michael@0: return false; michael@0: } michael@0: michael@0: let output = []; michael@0: michael@0: function process_type(t) michael@0: { michael@0: if ((t.kind == "class" || t.kind == "struct")) { michael@0: if (!t.isIncomplete && inheritsFrom(t, 'nsIFrame')) { michael@0: if (inheritsFrom(t, 'nsISupports')) michael@0: warning("nsIFrame derivative %s inherits from nsISupports but is not refcounted.".format(t.name), t.loc); michael@0: michael@0: let nonFrameBases = []; michael@0: michael@0: output.push('CLASS-DEF: %s'.format(t.name)); michael@0: michael@0: for each (let base in t.bases) { michael@0: if (inheritsFrom(base.type, 'nsIFrame')) { michael@0: output.push('%s -> %s;'.format(base.type.name, t.name)); michael@0: } michael@0: else if (base.type.name != 'nsQueryFrame') { michael@0: nonFrameBases.push(base.type.name); michael@0: } michael@0: } michael@0: michael@0: output.push('%s [label="%s%s"];'.format(t.name, t.name, michael@0: ["\\n(%s)".format(b) for each (b in nonFrameBases)].join(''))); michael@0: } michael@0: } michael@0: } michael@0: michael@0: let frameIIDRE = /::kFrameIID$/; michael@0: let queryFrameRE = /^do_QueryFrame::operator/; michael@0: michael@0: /* A list of class names T that have do_QueryFrame used */ michael@0: let needIDs = []; michael@0: michael@0: /* A map of class names that have a kFrameIID declared */ michael@0: let haveIDs = {}; michael@0: michael@0: // We match up needIDs with haveIDs at the end because static variables are michael@0: // not present in the .members array of a type michael@0: michael@0: function process_tree_decl(d) michael@0: { michael@0: d = dehydra_convert(d); michael@0: michael@0: if (d.name && frameIIDRE.exec(d.name)) { michael@0: haveIDs[d.memberOf.name] = 1; michael@0: } michael@0: } michael@0: michael@0: function process_cp_pre_genericize(d) michael@0: { michael@0: d = dehydra_convert(d); michael@0: if (queryFrameRE.exec(d.name) && d.template === undefined) { michael@0: let templtype = d.type.type.type; michael@0: while (templtype.typedef !== undefined) michael@0: templtype = templtype.typedef; michael@0: michael@0: needIDs.push([templtype.name, d.loc]); michael@0: } michael@0: } michael@0: michael@0: function input_end() michael@0: { michael@0: for each (let [name, loc] in needIDs) { michael@0: if (!haveIDs.hasOwnProperty(name)) { michael@0: error("nsQueryFrame<%s> found, but %s::kFrameIID is not declared".format(name, name), loc); michael@0: } michael@0: } michael@0: michael@0: if (output.length > 0) { michael@0: write_file(sys.aux_base_name + '.framedata', output.join('\n')); michael@0: } michael@0: }