update Ox.doc; add (some) inline comments in Ox.test

This commit is contained in:
rolux 2012-05-30 00:26:25 +02:00
parent 250db05abc
commit f7e58b05e9

View file

@ -20,6 +20,8 @@ Ox.doc <f> Generates documentation for annotated JavaScript
file <s> File name
line <n> Line number
name <s> Name of the item
order <[s]> Order of signature, arguments, properties
Present if the type of the item is "function"
properties <[o]|u> Properties (array of doc objects)
Present if the <code>type</code> of the item is
<code>"event"</code>, <code>"function"</code>
@ -30,10 +32,10 @@ Ox.doc <f> Generates documentation for annotated JavaScript
line <n> Line
type <s> Type (see Ox.tokenize for a list of types)
value <s> Value
summary <s> One-line summary
usage <[o]> Usage (array of doc objects)
returns <[o]> Return values (array of doc objects)
Present if the <code>type</code> of the item is
<code>"function"</code>.
summary <s> One-line summary
tests <[o]> Tests (array of test objects)
expected <s> Expected result
statement <s> Statement
@ -66,9 +68,9 @@ Ox.doc <f> Generates documentation for annotated JavaScript
'Magic constant'
> Ox.test.doc[1].description
'Bar per baz is a good indicator of an item\'s foo-ness.'
> Ox.test.doc[1].usage[0].types
> Ox.test.doc[1].signature[0].types
['number']
> Ox.test.doc[1].usage[0].summary
> Ox.test.doc[1].signature[0].summary
'Bar per baz, or NaN'
> Ox.test.doc[1].tests[1]
{expected: 'NaN', statement: 'My.foo({})'}
@ -78,9 +80,9 @@ Ox.doc = (function() {
item: /^(.+?) <(.+?)> (.+?)$/,
multiline: /^\/\*\@.*?\n([\w\W]+)\n.*?\@?\*\/$/,
script: /\n(\s*<script>s*\n[\w\W]+\n\s*<\/script>s*)/g,
signature: /(\(.*?\)) \->(.*)/,
singleline: /^\/\/@\s*(.*?)\s*$/,
test: /\n(\s*> .+\n.+?)/g,
usage: /\(.*?\)/
},
types = {
a: 'array', b: 'boolean', d: 'date',
@ -110,17 +112,21 @@ Ox.doc = (function() {
return matches && (
matches[2].indexOf('/') == -1 ||
'\'"'.indexOf(matches[2].slice(-2, -1)) > -1
) ? Ox.extend({
name: parseName(matches[1].trim()),
summary: matches[3].trim()
}, parseType(matches[2])) : null;
) ? Ox.extend(
parseName(matches[1]),
parseType(matches[2]),
{summary: matches[3].trim()}
) : null;
}
function parseName(string) {
var matches = re.usage.exec(string);
return matches ? matches[0] : string;
var matches = re.signature.exec(string);
return matches
? {signature: matches[1], name: matches[2].trim()}
: {name: string};
}
function parseNode(node) {
var item = parseItem(node.line), subitem;
var item = parseItem(node.line), order = [];
item.name = item.name.replace(/^\./, '');
node.nodes && node.nodes.forEach(function(node) {
var key, line = node.line, subitem;
if (!/^#/.test(node.line)) {
@ -130,17 +136,21 @@ Ox.doc = (function() {
item.tests = item.tests || [];
item.tests.push(parseTest(line));
} else if ((subitem = parseItem(line))) {
if (/^\(/.test(subitem.name)) {
item.usage = item.usage || [];
item.usage.push(parseNode(node));
if (subitem.signature) {
item.returns = item.returns || [];
item.returns.push(parseNode(node));
order.push('returns');
} else if (subitem.types[0] == 'event') {
item.events = item.events || [];
item.events.push(parseNode(node));
order.push('events');
} else {
key = item.types[0] == 'function'
? 'arguments' : 'properties'
&& !/^\./.test(subitem.name)
? 'arguments' : 'properties';
item[key] = item[key] || [];
item[key].push(parseNode(node));
order.push(key);
}
} else {
item.description = item.description
@ -148,6 +158,9 @@ Ox.doc = (function() {
}
}
});
if (item.types[0] == 'function') {
item.order = Ox.unique(order);
}
return item;
}
function parseScript(string) {
@ -183,6 +196,7 @@ Ox.doc = (function() {
.replace(re.script, encodeLinebreaks)
.replace(re.test, encodeLinebreaks)
.split('\n'),
parent,
tree = parseTree(lines);
if (re.item.test(tree.line)) {
// parse the tree's root node
@ -200,8 +214,17 @@ Ox.doc = (function() {
} else {
// property of a function item
lastItem = items[items.length - 1];
lastItem.properties = lastItem.properties || [];
lastItem.properties.push(item);
parent = lastItem.types[0] == 'function'
&& lastItem.returns
&& lastItem.returns[0].types[0] == 'object'
? lastItem.returns[0] : lastItem;
parent.properties = parent.properties || [];
parent.properties.push(item);
if (
parent.order && !Ox.contains(parent.order, 'properties')
) {
parent.order.push('properties');
}
// include leading linebreaks and whitespace
lastItem.source = lastItem.source.concat(
parseTokens(tokens[i], true)
@ -597,6 +620,7 @@ Ox.test <f> Takes JavaScript, runs inline tests, returns results
section <s|u> Section in the file
statement <s> Test statement
passed <b> True if actual result and expected result are equal
.data <o> undocumented
<script>
Ox.test.foo = function(item) {
return item.bar / item.baz;
@ -620,9 +644,16 @@ Ox.test <f> Takes JavaScript, runs inline tests, returns results
undefined
@*/
Ox.test = function(argument, callback) {
Ox.print('Ox.test', argument, '----------------------------------')
// Ansynchronous functions can be tested by calling Ox.test(actual,
// expected) in the callback. If Ox.test is called inside a test statement
// (unless at the beginning of the statement, which is a test for Ox.test),
// the call to Ox.test is patched by inserting the test statement string as
// the first argument of the Ox.test call, and Ox.test will branch when
// called with three arguments.
function runTests(items) {
var id = Ox.uid(), regexp = /(.+Ox\.test\()/, results = [];
// We have to create a globally accessible object so that synchronous
// and asynchronous tests can read, write and return the same data.
Ox.test.data[id] = {
callback: callback,
done: false,
@ -635,18 +666,20 @@ Ox.test = function(argument, callback) {
}) && item.tests.forEach(function(test) {
var actual, isAsync = regexp.test(test.statement);
if (isAsync) {
// Add a pending test
Ox.test.data[id].tests[test.statement] = {
name: item.name,
section: item.section
};
Ox.Log('TEST', 'XXX', test.statement);
// Patch the test statement
test.statement = test.statement.replace(
regexp,
"$1'" + test.statement.replace(/'/g, "\\'") + "', "
);
}
if (test.expected || test.statement.match(/Ox\.test\./)) {
// don't eval script tags without assignment to Ox.test.foo
// Eval the statement, unless it's a script tag that doesn't
// add a property to Ox.test
Ox.Log('TEST', test.statement);
actual = eval(test.statement);
}
@ -671,12 +704,15 @@ Ox.test = function(argument, callback) {
}
if (arguments.length == 2) {
if (Ox.typeOf(argument) == 'string' && Ox.contains(argument, '\n')) {
// source code
runTests(Ox.doc(argument))
} else {
argument = Ox.makeArray(argument);
if (Ox.typeOf(argument[0]) == 'string') {
// files
Ox.doc(argument, runTests);
} else {
// doc objects
runTests(argument);
}
}