Ox.doc: parse inherited properties

This commit is contained in:
rolux 2012-06-01 01:41:38 +02:00
parent ac82c3b30e
commit 4221d437ce

View file

@ -13,11 +13,16 @@ Ox.doc <f> Generates documentation for annotated JavaScript
arguments <[o]|u> Arguments (array of doc objects)
Present if the <code>type</code> of the item is
<code>"function"</code>.
description <s|u> Multi-line description with optional markup
See Ox.sanitizeHTML for details
class <s|u> Class of the item
default <s|u> Default value of the item
description <s|u> Multi-line description with some Markdown
See Ox.parseMarkdown for details
events <[o]|u> Events (array of doc objects)
Present if the item fires any events
file <s> File name
inherited <[o]|u> Inherited properties (array of doc objects)
Present if the item has a class, and any item in its inheritance
chain has (unshadowed) properties
line <n> Line number
name <s> Name of the item
order <[s]> Order of returns, arguments, properties
@ -35,11 +40,12 @@ Ox.doc <f> Generates documentation for annotated JavaScript
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
summary <s> One-line summary, with some Markdown
See Ox.parseMarkdown for details
tests <[o]> Tests (array of test objects)
expected <s> Expected result
statement <s> Statement
type <s> Type of the item
types <[s]> Types of the item
<script>
Ox.test.doc = Ox.doc([
'//@ My.FOO <n> Magic constant',
@ -85,17 +91,99 @@ Ox.doc = (function() {
test: /\n(\s*> .+\n.+?)/g,
},
types = {
a: 'array', b: 'boolean', d: 'date',
e: 'element', f: 'function', n: 'number',
o: 'object', r: 'regexp', s: 'string',
u: 'undefined', '*': 'value', '!': 'event'
a: 'array', b: 'boolean', d: 'date', e: 'error', f: 'function',
g: 'arguments', h: 'htmlelement', 'l': 'nodelist', n: 'number',
o: 'object', r: 'regexp', s: 'string', u: 'undefined',
'w': 'window', '*': 'any', '+': 'other', '!': 'event'
};
function addInheritedProperties(items) {
var constructors = getConstructors(items), instances = {}, nodes = {};
function hasProperty(item, property) {
var properties = item.properties || [],
inherited = item.inherited ? item.inherited.map(function(v) {
return v.properties;
}) : [];
return Ox.contains(properties.concat(inherited), property);
}
var foo = {};
constructors.forEach(function(constructor) {
var instance = Ox.last(constructor.returns);
instances[constructor.name] = instance;
nodes[constructor.name] = instance['class'];
});
Ox.print('CHAINS', getChains(nodes))
Ox.forEach(getChains(nodes), function(chain, childName) {
var child = instances[childName];
chain.forEach(function(parentName) {
var parent = instances[parentName] || null;
parent && parent.properties && parent.properties.forEach(function(property) {
if (!hasProperty(child, property)) {
if (!child.inherited) {
child.inherited = [];
}
if (!child.inherited.some(function(v) {
return v.name == parentName;
})) {
child.inherited.push({name: parentName, properties: []});
}
Ox.last(child.inherited).properties.push(property);
}
});
});
});
return items;
}
function decodeLinebreaks(match, submatch) {
return (submatch || match).replace(/\u21A9/g, '\n');
}
function encodeLinebreaks(match, submatch) {
return '\n' + (submatch || match).replace(/\n/g, '\u21A9');
}
function getChains(nodes) {
var chains = {}, sorted = [], visited = [];
function visit(name, stack) {
stack = stack || [];
if (Ox.contains(stack, name)) {
throw new Error(
'Circular dependency: ' + name + ' <-> ' + Ox.last(stack)
);
}
if (!Ox.contains(visited, name)) {
visited.push(name);
stack.push(name)
Ox.forEach(nodes, function(parent, name_) {
parent == name && visit(name_, stack);
});
sorted.unshift(name);
}
}
Ox.forEach(nodes, function(parent, name) {
visit(name);
});
sorted.forEach(function(name) {
chains[name] = [nodes[name]].concat(chains[nodes[name]] || [])
});
return chains;
}
function getConstructors(items) {
var constructors = [];
items.forEach(function(item) {
if (item.returns) {
Ox.forEach(item.returns, function(v) {
if (v['class']) {
constructors.push(item);
Ox.Break();
}
});
}
['arguments', 'properties', 'returns'].forEach(function(key) {
if (item[key]) {
constructors.concat(getConstructors(item[key]));
}
});
})
return constructors;
}
function getIndent(string) {
var indent = -1;
while (string[++indent] == ' ') {}
@ -312,7 +400,7 @@ Ox.doc = (function() {
function parseTypes(string) {
// returns {types: [""]}
// or {types: [""], default: ""}
// or {types: [""], super: ""}
// or {types: [""], class: ""}
var array,
isArray,
ret = {types: []},
@ -322,7 +410,7 @@ Ox.doc = (function() {
array = string.split(':');
string = array[0];
if (array.length == 2) {
ret['super'] = array[1];
ret['class'] = array[1];
}
}
string.split('|').forEach(function(string) {
@ -351,15 +439,19 @@ Ox.doc = (function() {
return function(argument, callback) {
var counter = 0, items = [], ret;
if (arguments.length == 1) {
ret = parseSource(argument);
// source
ret = addInheritedProperties(parseSource(argument));
} else {
// file(s)
argument = Ox.makeArray(argument);
argument.forEach(function(file) {
Ox.get(file, function(source) {
items = items.concat(
parseSource(source, file.split('?')[0])
);
++counter == argument.length && callback(items);
if (++counter == argument.length) {
callback(addInheritedProperties(items));
}
});
})
}