match Node.js' console.log/error/info/warn/trace; speed up -X option (#298)

This commit is contained in:
Jeff Williams 2013-04-18 23:16:47 -07:00
parent 5c69bbd289
commit 8c65d81e23
5 changed files with 99 additions and 157 deletions

View File

@ -231,7 +231,7 @@ function main() {
borrow.resolveBorrows(docs);
if (env.opts.explain) {
console.log(docs);
dump(docs);
process.exit(0);
}

View File

@ -1,155 +1,94 @@
/**
Recursively print out all names and values in a data structure.
@module jsdoc/util/dumper
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
* Recursively print out all names and values in a data structure.
* @module jsdoc/util/dumper
* @author Michael Mathews <micmath@gmail.com>
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
const INDENTATION = ' '; // 4 spaces
var indentBy,
output;
var util = require('util');
function pad(depth) {
var padding = '';
while (depth--) {
padding += INDENTATION;
var seenItems = [];
function seen(object) {
if (seenItems.indexOf(object) !== -1) {
return true;
}
return padding;
}
/**
@param {string} openingBrace - The opening brace to add, like "{".
@private
@inner
@memberof module:jsdoc/util/dumper
*/
function indent(openingBrace) {
indentBy++;
if (openingBrace) { output += openingBrace + '\n'; }
}
/**
@param {string|boolean} closingBrace - The closing brace to add, like "}" or if boolean
`false` no closing brace or trailing newline.
@private
@inner
@memberof module:jsdoc/util/dumper
*/
function outdent(closingBrace) {
indentBy--;
output = output.replace(/,\n$/, '\n'); // trim trailing comma
if (closingBrace === false) { output = output.replace(/\n$/, ''); }
else if (closingBrace) { output += pad(indentBy) + closingBrace + ',\n'; }
}
var seen = [];
seen.has = function(object) {
for (var i = 0, l = seen.length; i < l; i++) {
if (seen[i] === object) { return true; }
}
return false;
};
function stringify(o) {
return JSON.stringify(o);
}
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
if (o === null) { return 'null'; }
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
return ''+stringify(o);
}
}
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
return (typeof o === 'object' && typeof o.constructor === 'undefined');
}
function isArray(o) {
return o && (o instanceof Array) || o.constructor === Array;
}
function isRegExp(o) {
return (o instanceof RegExp) ||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
}
function isDate(o) {
return o && (o instanceof Date) ||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
// some objects are unwalkable, like Java native objects
function isUnwalkable(o) {
return (o && typeof o === 'object' && typeof o.constructor === 'undefined');
}
function isFunction(o) {
return o && (typeof o === 'function' || o instanceof Function);// ||
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
return (o && typeof o === 'function' || o instanceof Function);
}
function isObject(o) {
return o && o instanceof Object ||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
return o && o instanceof Object ||
(o && typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
}
function walk(object) {
var value = getValue(object);
if (value) {
output += value + ',\n';
function checkCircularRefs(o, func) {
if ( seen(o) ) {
return '<CircularRef>';
}
else if ( isUnwalkable(object) ) {
output += '<Object>,\n';
else {
seenItems.push(o);
return func.call(this, o);
}
else if ( isRegExp(object) ) {
output += '<RegExp ' + object + '>,\n';
}
function walk(o) {
var result;
if ( isUnwalkable(o) ) {
result = '<Object>';
}
else if ( isDate(object) ) {
output += '<Date ' + object.toUTCString() + '>,\n';
else if ( o === undefined ) {
result = 'undefined';
}
else if ( isFunction(object) ) {
output += '<Function' + (object.name? ' '+ object.name : '') + '>,\n';
else if ( Array.isArray(o) ) {
result = checkCircularRefs(o, function(arr) {
var newArray = [];
arr.forEach(function(item) {
newArray.push( walk(item) );
});
return newArray;
});
}
else if ( isArray(object) ) {
if ( seen.has(object) ) {
output += '<CircularRef>,\n';
return;
}
else {
seen.push(object);
}
indent('[');
for (var i = 0, leni = object.length; i < leni; i++) {
output += pad(indentBy); // + i + ': ';
walk( object[i] );
}
outdent(']');
else if ( util.isRegExp(o) ) {
result = '<RegExp ' + o + '>';
}
else if ( isObject(object) ) {
if ( seen.has(object) ) {
output += '<CircularRef>,\n';
return;
}
else {
seen.push(object);
}
indent('{');
for (var p in object) {
if ( object.hasOwnProperty(p) ) {
output += pad(indentBy) + stringify(p) + ': ';
walk( object[p] );
}
}
outdent('}');
else if ( util.isDate(o) ) {
result = '<Date ' + o.toUTCString() + '>';
}
else if ( isFunction(o) ) {
result = '<Function' + (o.name ? ' ' + o.name : '') + '>';
}
else if ( isObject(o) && o !== null ) {
result = checkCircularRefs(o, function(obj) {
var newObj = {};
Object.keys(obj).forEach(function(key) {
newObj[key] = walk(obj[key]);
});
return newObj;
});
}
// should be safe to JSON.stringify() everything else
else {
result = o;
}
return result;
}
/**
@param {any} object
* @param {*} object
*/
exports.dump = function(object) {
indentBy = 0;
output = '';
walk(object);
outdent(false);
return output;
return JSON.stringify(walk(object), null, 4);
};

View File

@ -55,30 +55,31 @@ clearInterval = null;
* Emulate Node.js console functions.
* @see http://nodejs.org/api/stdio.html
*/
console = {
debug: function() {
// TODO
},
error: function() {
// TODO
},
log: function(/*...*/) {
// TODO: make this consistent with Node.js
var args = Array.prototype.slice.call(arguments, 0),
dumper = dumper || require('jsdoc/util/dumper');
for (var i = 0, len = args.length; i < len; i++) {
if (typeof args[i] !== 'string') {
args[i] = dumper.dump(args[i]);
}
}
java.lang.System.out.println( args.join(' ') );
},
trace: function() {
// TODO
console = (function() {
function println(stream, args) {
java.lang.System[stream].println( require('util').format.apply(this, args) );
}
};
return {
error: function() {
println('err', arguments);
},
info: function() {
println('out', arguments);
},
log: function() {
println('out', arguments);
},
trace: function(label) {
// this puts some extra junk at the top of the stack trace, but it's close enough
var e = new java.lang.Exception(label || 'Trace');
e.printStackTrace();
},
warn: function() {
println('err', arguments);
}
};
})();
/**
* Emulate Node.js process functions.

View File

@ -210,7 +210,7 @@ exports.publish = function(data, opts) {
console.log( xml('jsdoc', root) );
}
else {
console.log(root);
dump(root);
}
}
else {

View File

@ -1,3 +1,4 @@
/*global describe: true, expect: true, it: true */
describe("common/dumper", function() {
var common = {dumper: require('jsdoc/util/dumper')};
@ -38,20 +39,21 @@ describe("common/dumper", function() {
});
it("can dump undefined values", function() {
expect(common.dumper.dump(undefined)).toEqual('undefined');
expect(common.dumper.dump(undefined)).toEqual('"undefined"');
});
it("can dump regex values", function() {
expect(common.dumper.dump(/^[Ff]oo$/gi)).toEqual('<RegExp /^[Ff]oo$/gi>');
expect(common.dumper.dump(/^[Ff]oo$/gi)).toEqual('"<RegExp /^[Ff]oo$/gi>"');
});
it("can dump date values", function() {
expect(common.dumper.dump(new Date('January 1, 1901 GMT'))).toEqual('<Date Tue, 01 Jan 1901 00:00:00 GMT>');
expect(common.dumper.dump(new Date('January 1, 1901 GMT')))
.toEqual('"<Date Tue, 01 Jan 1901 00:00:00 GMT>"');
});
it("can dump function values", function() {
expect(common.dumper.dump(function myFunc(){})).toEqual('<Function myFunc>');
expect(common.dumper.dump(function(){})).toEqual('<Function>');
expect(common.dumper.dump(function myFunc(){})).toEqual('"<Function myFunc>"');
expect(common.dumper.dump(function(){})).toEqual('"<Function>"');
});
it("can dump array values", function() {
@ -84,7 +86,7 @@ describe("common/dumper", function() {
var actual = common.dumper.dump(
[undefined, null, new Foo(), 1, true, 'hello\n"world', new Error('oops'), /foo/gi, new Date('December 26, 2010 GMT'), {f: function myFunc(){}, o: {a:1}}]
),
expected = '[\n undefined,\n null,\n {\n },\n 1,\n true,\n "hello\\n\\"world",\n {\n "message": "oops"\n },\n <RegExp /foo/gi>,\n <Date Sun, 26 Dec 2010 00:00:00 GMT>,\n {\n "f": <Function myFunc>,\n "o": {\n "a": 1\n }\n }\n]';
expected = '[\n "undefined",\n null,\n {},\n 1,\n true,\n "hello\\n\\"world",\n {\n "message": "oops"\n },\n "<RegExp /foo/gi>",\n "<Date Sun, 26 Dec 2010 00:00:00 GMT>",\n {\n "f": "<Function myFunc>",\n "o": {\n "a": 1\n }\n }\n]';
expect(actual).toEqual(expected);
});
@ -94,7 +96,7 @@ describe("common/dumper", function() {
a.b = a;
var actual = common.dumper.dump(a),
expected = '{\n "b": <CircularRef>\n}';
expected = '{\n "b": "<CircularRef>"\n}';
expect(actual).toEqual(expected);
});