From e23f644ae807736fc9707d2762fc0262918d273f Mon Sep 17 00:00:00 2001 From: ben hockey Date: Sat, 23 Mar 2013 01:41:35 -0500 Subject: [PATCH] defer resolving the annotated object. by resolving this in the exporter, we can avoid a race condtion where sometimes relatedModule had not been indicated when it should have been. --- lib/exporter/dojov1.js | 76 +++++++++++++++++++++++++++++++++++++++- lib/processor/dojodoc.js | 52 +++++---------------------- 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/lib/exporter/dojov1.js b/lib/exporter/dojov1.js index b9a3a06..cd5e244 100644 --- a/lib/exporter/dojov1.js +++ b/lib/exporter/dojov1.js @@ -1,4 +1,12 @@ -define([ '../Module', '../Value', './util', '../console', '../node!fs' ], function (Module, Value, util, console, fs) { +define([ + 'dojo/string', + '../Module', + '../Value', + './util', + '../console', + 'dojo/node!fs', +], function (stringUtil, Module, Value, util, console, fs) { + /** * Takes information from metadata stored alongside a Value and adds it to the output. * @param node The node to add metadata to. @@ -34,6 +42,66 @@ define([ '../Module', '../Value', './util', '../console', '../node!fs' ], functi } } + /** + * Given metadata with a type annotation, attempt to resolve the annotated type as an object and (hackily) apply + * information about the object’s default properties to the metadata description property. + */ + function processTypeAnnotation(/**Object*/ metadata) { + if (!metadata.type || typeof metadata.type === 'string') { + return; + } + + var propertyTemplate = '
  • ${key}${type}${summary}
  • ', + annotationObject = metadata.type, + additionalDescription = ''; + + if (annotationObject.relatedModule) { + metadata.type = annotationObject.relatedModule.id; + return; + } + + metadata.type = 'Object'; + additionalDescription += '

    ' + (metadata.description ? + 'The following properties are supported:' : + 'An object with the following properties:') + '

    '; + } + /** * Takes an array of return Values and processes it for return types, discarding all * duplicates, and applies the resulting list of properties to the node given in returnsNode. @@ -67,6 +135,9 @@ define([ '../Module', '../Value', './util', '../console', '../node!fs' ], functi i; for (i = 0; (parameter = property.parameters[i]); ++i) { + if (typeof parameter.metadata.type !== 'string') { + processTypeAnnotation(parameter.metadata); + } parameterType = parameter.metadata.type || parameter.type || 'unknown'; parameterNode = parametersNode.createNode('parameter', { name: parameter.name, @@ -105,6 +176,9 @@ define([ '../Module', '../Value', './util', '../console', '../node!fs' ], functi propertyNode; function makePropertyObject(name, value) { + if (typeof value.metadata.type !== 'string') { + processTypeAnnotation(value.metadata); + } var object = { name: name, scope: scope, diff --git a/lib/processor/dojodoc.js b/lib/processor/dojodoc.js index 5c0ad8a..9639833 100644 --- a/lib/processor/dojodoc.js +++ b/lib/processor/dojodoc.js @@ -50,7 +50,7 @@ define([ if (source[k] instanceof Array && destination[k] instanceof Array) { destination[k] = destination[k].concat(source[k]); } - else if (k === 'type') { + else if (k === 'type' && typeof source[k] === 'string') { destination[k] = source[k].replace(optionalTypeRe, ''); } else if (typeof source[k] !== 'string' || trim(source[k])) { @@ -113,60 +113,24 @@ define([ } /** - * Given metadata with a type annotation, attempt to resolve the annotated type as an object and (hackily) apply - * information about the object’s default properties to the metadata description property. - * TODO: This should really end up happening in the dojov1 exporter instead. + * Given metadata with a type annotation, attempt to resolve the annotated type as an object and + * provide that object to the exporter as the type property of the metadata. */ function processTypeAnnotation(/**Object*/ metadata) { if (!metadata.type) { return; } - var propertyTemplate = '\n* ${key}${type}${summary}', - annotationObject = env.scope.getVariable(metadata.type.replace(/[^\w$\.]+$/g, '').split('.')), - additionalDescription = ''; + var annotationObject = env.scope.getVariable(metadata.type.replace(/[^\w$\.]+$/g, '').split('.')); if (!annotationObject || annotationObject.type === Value.TYPE_UNDEFINED || /* not a built-in */ !annotationObject.file) { return; } - if (annotationObject.relatedModule) { - metadata.type = annotationObject.relatedModule.id; - return; - } - - // TODO: The fact that evaluate exists on annotation objects seems to indicate that we’re failing to - // evaluate all function expressions; this might be an issue - annotationObject.evaluate && annotationObject.evaluate(); - - metadata.type = 'Object'; - additionalDescription += metadata.description ? - '\n\nThe following properties are supported:\n' : - 'An object with the following properties:\n'; - - (function readProperties(object) { - var propertyMetadata; - for (var k in object.properties) { - if (_hasOwnProperty.call(object.properties, k)) { - // Type descriptor could be a plain JS object, or could be a constructor. It is often the - // latter. - if (k === 'prototype') { - readProperties(object.properties[k]); - } - // Filter out built-ins and constructor properties which come from dojo/_base/declare - else if (k !== 'constructor' && object.properties[k].file) { - propertyMetadata = object.properties[k].metadata; - additionalDescription += stringUtil.substitute(propertyTemplate, { - key: k, - type: propertyMetadata.type ? ' (' + propertyMetadata.type + (propertyMetadata.isOptional ? ', optional' : '') + ')' : '', - summary: propertyMetadata.summary ? ': ' + propertyMetadata.summary : '' - }); - } - } - } - }(annotationObject)); - - metadata.description = (metadata.description || '') + parseMarkdown(additionalDescription); + // defer resolving this to do it in the exporter. annotationObject might be the return + // value of the module currently being processed and in that case it won't have been tagged + // with a relatedModule yet. + metadata.type = annotationObject; } /**