Merge pull request #2644 from ahocevar/extends-externs

Add @extends annotations to generated externs
This commit is contained in:
Andreas Hocevar
2014-08-29 10:49:42 +02:00
4 changed files with 68 additions and 16 deletions

View File

@@ -12,6 +12,6 @@
"plugins": [ "plugins": [
"config/jsdoc/info/api-plugin", "config/jsdoc/info/api-plugin",
"config/jsdoc/info/define-plugin", "config/jsdoc/info/define-plugin",
"config/jsdoc/info/interface-plugin" "config/jsdoc/info/virtual-plugin"
] ]
} }

View File

@@ -22,15 +22,29 @@ exports.publish = function(data, opts) {
return types; return types;
} }
function replaceUnknownTypes(item) {
item.types.forEach(function(type, index) {
if (!(type in names)) {
item.types[index] = '*';
}
});
}
// get all doclets with the "api" property or define (excluding events) or // get all doclets with the "api" property or define (excluding events) or
// with olx namespace // with olx namespace
var classes = {};
var docs = data( var docs = data(
[ [
{define: {isObject: true}}, {define: {isObject: true}},
{api: {isString: true}},
{'interface': {is: true}},
function() { function() {
return this.meta && (/[\\\/]externs$/).test(this.meta.path); if (this.kind == 'class') {
if (!('extends' in this) || typeof this.api == 'string') {
classes[this.longname] = this;
return true;
}
}
return (typeof this.api == 'string' ||
this.meta && (/[\\\/]externs$/).test(this.meta.path));
} }
], ],
{kind: {'!is': 'file'}}, {kind: {'!is': 'file'}},
@@ -41,7 +55,9 @@ exports.publish = function(data, opts) {
var defines = []; var defines = [];
var typedefs = []; var typedefs = [];
var externs = []; var externs = [];
var interfaces = []; var base = [];
var augments = {};
var names = {};
docs.filter(function(doc) { docs.filter(function(doc) {
var include = true; var include = true;
var constructor = doc.memberof; var constructor = doc.memberof;
@@ -88,6 +104,12 @@ exports.publish = function(data, opts) {
stability: doc.api, stability: doc.api,
path: path.join(doc.meta.path, doc.meta.filename) path: path.join(doc.meta.path, doc.meta.filename)
}; };
if (doc.augments) {
symbol.extends = doc.augments[0];
}
if (doc.virtual) {
symbol.virtual = true;
}
if (doc.type) { if (doc.type) {
symbol.types = getTypes(doc.type.names); symbol.types = getTypes(doc.type.names);
} }
@@ -128,9 +150,34 @@ exports.publish = function(data, opts) {
return true; return true;
}); });
} }
var target = isExterns ? externs : (doc.interface ? interfaces : symbols);
var target = isExterns ? externs : (doc.api ? symbols : base);
target.push(symbol); target.push(symbol);
names[symbol.name] = true;
if (doc.api && symbol.extends) {
while (symbol.extends in classes && !classes[symbol.extends].api &&
classes[symbol.extends].augments) {
symbol.extends = classes[symbol.extends].augments[0];
} }
if (symbol.extends) {
augments[symbol.extends] = true;
}
}
}
});
base = base.filter(function(symbol) {
var pass = symbol.name in augments || symbol.virtual;
if (pass) {
if (symbol.params) {
symbol.params.forEach(replaceUnknownTypes);
}
if (symbol.returns) {
symbol.returns.forEach(replaceUnknownTypes);
}
}
return pass;
}); });
process.stdout.write( process.stdout.write(
@@ -139,7 +186,7 @@ exports.publish = function(data, opts) {
defines: defines, defines: defines,
typedefs: typedefs, typedefs: typedefs,
externs: externs, externs: externs,
interfaces: interfaces base: base
}, null, 2)); }, null, 2));
}; };

View File

@@ -1,5 +1,5 @@
/** /**
* Handle the interface annotation. * Handle the interface and abstract annotations.
* @param {Object} dictionary The tag dictionary. * @param {Object} dictionary The tag dictionary.
*/ */
exports.defineTags = function(dictionary) { exports.defineTags = function(dictionary) {
@@ -9,7 +9,7 @@ exports.defineTags = function(dictionary) {
mustHaveValue: false, mustHaveValue: false,
onTagged: function(doclet, tag) { onTagged: function(doclet, tag) {
classTag.onTagged.apply(this, arguments); classTag.onTagged.apply(this, arguments);
doclet.interface = true; doclet.virtual = true;
} }
}); });

View File

@@ -7,6 +7,8 @@ var nomnom = require('nomnom');
var generateInfo = require('./generate-info'); var generateInfo = require('./generate-info');
var googRegEx = /^goog\..*$/;
/** /**
* Read the symbols from info file. * Read the symbols from info file.
* @param {funciton(Error, Array.<string>, Array.<Object>)} callback Called * @param {funciton(Error, Array.<string>, Array.<Object>)} callback Called
@@ -19,7 +21,7 @@ function getInfo(callback) {
return; return;
} }
var info = require('../build/info.json'); var info = require('../build/info.json');
callback(null, info.typedefs, info.symbols, info.externs, info.interfaces); callback(null, info.typedefs, info.symbols, info.externs, info.base);
}); });
} }
@@ -29,11 +31,11 @@ function getInfo(callback) {
* @param {Array.<Object>} typedefs List of typedefs. * @param {Array.<Object>} typedefs List of typedefs.
* @param {Array.<Object>} symbols List of symbols. * @param {Array.<Object>} symbols List of symbols.
* @param {Array.<Object>} externs List of externs. * @param {Array.<Object>} externs List of externs.
* @param {Array.<Object>} externs List of interfaces. * @param {Array.<Object>} base List of base.
* @param {string|undefined} namespace Target object for exported symbols. * @param {string|undefined} namespace Target object for exported symbols.
* @return {string} Export code. * @return {string} Export code.
*/ */
function generateExterns(typedefs, symbols, externs, interfaces) { function generateExterns(typedefs, symbols, externs, base) {
var lines = []; var lines = [];
var processedSymbols = {}; var processedSymbols = {};
var constructors = {}; var constructors = {};
@@ -67,7 +69,7 @@ function generateExterns(typedefs, symbols, externs, interfaces) {
function noGoogTypes(typesWithGoog) { function noGoogTypes(typesWithGoog) {
var typesWithoutGoog = []; var typesWithoutGoog = [];
typesWithGoog.forEach(function(type) { typesWithGoog.forEach(function(type) {
typesWithoutGoog.push(type.replace(/^goog\..*$/, '*')); typesWithoutGoog.push(type.replace(googRegEx, '*'));
}); });
return typesWithoutGoog; return typesWithoutGoog;
} }
@@ -93,6 +95,9 @@ function generateExterns(typedefs, symbols, externs, interfaces) {
if (symbol.kind === 'class') { if (symbol.kind === 'class') {
constructors[name] = true; constructors[name] = true;
lines.push(' * @constructor'); lines.push(' * @constructor');
if (symbol.extends && !googRegEx.test(symbol.extends)) {
lines.push(' * @extends {' + symbol.extends + '}');
}
} }
if (symbol.types) { if (symbol.types) {
lines.push(' * @type {' + noGoogTypes(symbol.types).join('|') + '}'); lines.push(' * @type {' + noGoogTypes(symbol.types).join('|') + '}');
@@ -127,7 +132,7 @@ function generateExterns(typedefs, symbols, externs, interfaces) {
externs.forEach(processSymbol); externs.forEach(processSymbol);
interfaces.forEach(processSymbol); base.forEach(processSymbol);
symbols.forEach(processSymbol); symbols.forEach(processSymbol);
@@ -153,10 +158,10 @@ function generateExterns(typedefs, symbols, externs, interfaces) {
function main(callback) { function main(callback) {
async.waterfall([ async.waterfall([
getInfo, getInfo,
function(typedefs, symbols, externs, interfaces, done) { function(typedefs, symbols, externs, base, done) {
var code, err; var code, err;
try { try {
code = generateExterns(typedefs, symbols, externs, interfaces); code = generateExterns(typedefs, symbols, externs, base);
} catch (e) { } catch (e) {
err = e; err = e;
} }