diff --git a/lib/infer/membership.js b/lib/infer/membership.js index b5618f145..062dad3c4 100644 --- a/lib/infer/membership.js +++ b/lib/infer/membership.js @@ -7,24 +7,31 @@ var n = require('babel-types'), isJSDocComment = require('../../lib/is_jsdoc_comment'), parse = require('../../lib/parse'); +function inferModuleName(comment) { + return (comment.kind === 'module' && comment.name) || + pathParse(comment.context.file).name; +} + /** * Given an AST node, try to find a comment in front of it that * has a `lends` tag, and if it has that, return the tag, split by * .s. * * @private - * @param {Object} node AST node + * @param {Object} path AST node * @returns {string|undefined} lends identifier, if any */ -function findLendsIdentifiers(node) { - if (!node || !node.leadingComments) { +function findLendsIdentifiers(path) { + if (!path || !path.get('leadingComments')) { return; } - for (var i = 0; i < node.leadingComments.length; i++) { - var comment = node.leadingComments[i]; - if (isJSDocComment(comment)) { - var lends = parse(comment.value).lends; + var leadingComments = path.get('leadingComments'); + + for (var i = 0; i < leadingComments.length; i++) { + var comment = leadingComments[i]; + if (isJSDocComment(comment.node)) { + var lends = parse(comment.node.value).lends; if (lends) { return lends.split('.'); } @@ -33,13 +40,16 @@ function findLendsIdentifiers(node) { } /** - * Extract and return the identifiers for expressions of type this.foo + * Extract and return the identifiers for expressions of + * type this.foo * - * @param {NodePath} path AssignmentExpression, MemberExpression, or Identifier + * @param {NodePath} path AssignmentExpression, MemberExpression, + * or Identifier + * @param {Comment} comment * @returns {Array} identifiers * @private */ -function extractThis(path) { +function extractThis(path, comment) { var identifiers = []; path.traverse({ @@ -60,14 +70,22 @@ function extractThis(path) { identifiers.push(scope.path.parentPath.parentPath.node.id.name, 'prototype'); } + // function OldClass() { this.foo = 1 } if (n.isFunctionDeclaration(scope.block)) { - identifiers.push(scope.block.id.name, 'prototype'); - } else if (n.isFunctionExpression(scope.block)) { - if (n.isVariableDeclarator(scope.path.parentPath)) { + // named function like + // function OldClass() { ... } + if (scope.block.id) { + identifiers.push(scope.block.id.name, 'prototype'); + } else if (n.isExportDefaultDeclaration(path.scope.parentBlock)) { + identifiers.push(inferModuleName(comment)); + } + // var Binding = function OldClass() { this.foo = 1 } + } else if (n.isFunctionExpression((scope.block))) { + if (scope.path.parentPath.isVariableDeclarator()) { /** var Bar = function(foo) { this.foo = foo; }; */ identifiers = identifiers .concat(scope.path.parentPath.get('id').node.name).concat('prototype'); - } else if (n.isAssignmentExpression(scope.path.parentPath)) { + } else if (scope.path.parentPath.isAssignmentExpression()) { /** this.Bar = function(foo) { this.foo = foo; }; */ identifiers = identifiers .concat(extractIdentifiers(scope.path.parentPath.get('left'))).concat('prototype'); @@ -169,10 +187,6 @@ function normalizeMemberof(comment/*: Comment*/)/*: Comment */ { module.exports = function () { var currentModule; - function inferModuleName(comment) { - return (comment.kind === 'module' && comment.name) || - pathParse(comment.context.file).name; - } /** * Set `memberof` and `instance`/`static` tags on `comment` based on the @@ -185,13 +199,13 @@ module.exports = function () { * @param {Array} identifiers array of identifier names * @param {string} explicitScope if derived from an es6 class, whether or * not this method had the static keyword - * @returns {undefined} mutates `comment` + * @returns {Comment} returns mutated `comment` * @private */ function inferMembershipFromIdentifiers(comment, identifiers, explicitScope) { if (identifiers.length === 1 && identifiers[0] === 'module' && comment.name === 'exports') { comment.name = inferModuleName(currentModule || comment); - return; + return comment; } /* @@ -215,142 +229,166 @@ module.exports = function () { comment.scope = 'static'; } } + return comment; } - return function inferMembership(comment/*: Comment */) { - + function shouldSkipInference(comment/*: Comment */)/*: boolean */ { + // If someone uses the @name tag, they explicitly ask for inference + // to be skipped. if (comment.tags.some(tag => tag.title === 'name')) { - return comment; + return true; } - if (comment.kind === 'module') { - currentModule = comment; + // Lends tags are go-betweens that let people reassign membership + // in bulk: they themselves don't get an inference step + if (comment.lends) { + return true; } - if (comment.lends) { + // If this chunk doesn't have code attached, like if it was the result + // of a polyglot parse, don't try to infer anything. + if (!comment.context.ast) { + return true; + } + + return false; + } + + return function inferMembership(comment/*: Comment */) { + + // First skip inference if the user indicates it or if it isn't possible. + if (shouldSkipInference(comment)) { return comment; } + // If someone explicitly specifies the parent of this chunk, don't + // try to infer it, just return what they specified. if (comment.memberof) { return normalizeMemberof(comment); } - if (!comment.context.ast) { - return comment; + if (comment.kind === 'module') { + currentModule = comment; } var path = comment.context.ast; - var identifiers; - + // INFERENCE =============================================================== // Deal with an oddity of espree: the jsdoc comment is attached to a different // node in the two expressions `a.b = c` vs `a.b = function () {}`. - if (n.isExpressionStatement(path.node) && - n.isAssignmentExpression(path.node.expression) && - n.isMemberExpression(path.node.expression.left)) { + if (path.isExpressionStatement() && + path.get('expression').isAssignmentExpression() && + path.get('expression').get('left').isMemberExpression()) { path = path.get('expression').get('left'); } // Same as above but for `b: c` vs `b: function () {}`. - if (n.isObjectProperty(path.node) && - n.isIdentifier(path.node.key)) { + if (path.isObjectProperty() && + path.get('key').isIdentifier()) { path = path.get('key'); } + // Forms: + // // Foo.bar = ...; // Foo.prototype.bar = ...; // Foo.bar.baz = ...; - if (n.isMemberExpression(path.node)) { - identifiers = [].concat( - extractThis(path), + // + // Lends is not supported in this codepath. + if (path.isMemberExpression()) { + var memberIdentifiers = [].concat( + extractThis(path, comment), extractIdentifiers(path) ); - if (identifiers.length >= 2) { - inferMembershipFromIdentifiers(comment, identifiers.slice(0, -1)); + if (memberIdentifiers.length >= 2) { + return inferMembershipFromIdentifiers(comment, memberIdentifiers.slice(0, -1)); } + return comment; } - // /** @lends Foo */{ bar: ... } - if (n.isIdentifier(path.node) && - n.isObjectProperty(path.parentPath) && - n.isObjectExpression(path.parentPath.parentPath)) { - // The @lends comment is sometimes attached to the first property rather than - // the object expression itself. - identifiers = findLendsIdentifiers(path.parentPath.parentPath.node) || - findLendsIdentifiers(path.parentPath.parentPath.node.properties[0]); - if (identifiers) { - inferMembershipFromIdentifiers(comment, identifiers); - } - } + // Like straight membership, classes don't need + // to support lends. + // + // class Foo { bar() { } } + // var Foo = class { bar() { } } + // class Foo { prop: T } + // var Foo = class { prop: T } + if ((path.isClassMethod() || path.isClassProperty()) && + path.parentPath.isClassBody() && + path.parentPath.parentPath.isClass()) { - // Foo = { bar: ... }; - // Foo.prototype = { bar: ... }; - // Foo.bar = { baz: ... }; - if (n.isIdentifier(path.node) && - n.isObjectProperty(path.parentPath) && - n.isObjectExpression(path.parentPath.parentPath) && - n.isAssignmentExpression(path.parentPath.parentPath.parentPath)) { - identifiers = extractIdentifiers(path.parentPath.parentPath.parentPath.get('left')); - if (identifiers.length >= 1) { - inferMembershipFromIdentifiers(comment, identifiers); + var scope = 'instance'; + if (path.node.static == true) { + scope = 'static'; } - } - // Shorthand methods on ordinary objects - if (n.isObjectMethod(path.node) && - n.isObjectExpression(path.parentPath)) { - - // Foo = { bar() {} }; - // Foo.prototype = { bar() {} }; - // Foo.bar = { baz() {} }; - if (n.isAssignmentExpression(path.parentPath.parentPath)) { - identifiers = extractIdentifiers(path.parentPath.parentPath.get('left')); - if (identifiers.length >= 1) { - inferMembershipFromIdentifiers(comment, identifiers); - } + if (path.parentPath.parentPath.isExpression()) { + return inferMembershipFromIdentifiers(comment, + extractIdentifiers(path.parentPath.parentPath.parentPath.get('left')), + scope); } - // var Foo = { bar() {} }; - if (n.isVariableDeclarator(path.parentPath.parentPath)) { - identifiers = [path.parentPath.parentPath.get('id').node.name]; - inferMembershipFromIdentifiers(comment, identifiers); + var declarationNode = path.parentPath.parentPath.node; + if (!declarationNode.id) { + // export default function () {} + // export default class {} + // Use module name instead. + return inferMembershipFromIdentifiers(comment, [pathParse(comment.context.file).name], scope); } + + return inferMembershipFromIdentifiers(comment, [declarationNode.id.name], scope); } - // var Foo = { bar: ... } - if (n.isIdentifier(path) && - n.isObjectProperty(path.parentPath) && - n.isObjectExpression(path.parentPath.parentPath) && - n.isVariableDeclarator(path.parentPath.parentPath.parentPath)) { - identifiers = [path.parentPath.parentPath.parentPath.node.id.name]; - inferMembershipFromIdentifiers(comment, identifiers); + // Whether something is an ObjectMethod (shorthand like foo() {} ) + // or ObjectProperty (old fashioned like foo: function() {} ) + // doesn't matter for the membership phase, as long as we end up knowing + // that it belongs to an object. So we first establish objectParent, + // and then have the logic for the numerous ways an object can be named. + var objectParent; + + if (path.isIdentifier() && + path.parentPath.isObjectProperty() && + path.parentPath.parentPath.isObjectExpression()) { + objectParent = path.parentPath.parentPath; + } else if (path.isObjectMethod() && + path.parentPath.isObjectExpression()) { + objectParent = path.parentPath; } - // class Foo { bar() { } } - // var Foo = class { bar() { } } - // class Foo { prop: T } - // var Foo = class { prop: T } - if ((n.isClassMethod(path) || n.isClassProperty(path)) && - n.isClassBody(path.parentPath) && - n.isClass(path.parentPath.parentPath)) { - if (n.isExpression(path.parentPath.parentPath)) { - identifiers = extractIdentifiers(path.parentPath.parentPath.parentPath.get('left')); - } else { - var declarationNode = path.parentPath.parentPath.node; - if (!declarationNode.id) { - // export default function () {} - // export default class {} - // Use module name instead. - identifiers = [pathParse(comment.context.file).name]; - } else { - identifiers = [declarationNode.id.name]; - } - } - var scope = 'instance'; - if (path.node.static == true) { - scope = 'static'; + // Confirm that the thing being documented is a property of an object. + if (objectParent) { + + // The @lends comment is sometimes attached to the first property rather than + // the object expression itself. + var lendsIdentifiers = findLendsIdentifiers(objectParent) || + findLendsIdentifiers(objectParent.get('properties')[0]); + + if (lendsIdentifiers) { + + return inferMembershipFromIdentifiers(comment, lendsIdentifiers); + + } else if (objectParent.parentPath.isAssignmentExpression()) { + + // Foo = { ... }; + // Foo.prototype = { ... }; + // Foo.bar = { ... }; + return inferMembershipFromIdentifiers(comment, + extractIdentifiers(objectParent.parentPath.get('left'))); + + } else if (objectParent.parentPath.isVariableDeclarator()) { + + // var Foo = { ... }; + return inferMembershipFromIdentifiers(comment, + [objectParent.parentPath.get('id').node.name]); + + } else if (objectParent.parentPath.isExportDefaultDeclaration()) { + + // export default { ... }; + return inferMembershipFromIdentifiers(comment, + [inferModuleName(currentModule || comment)]); + } - inferMembershipFromIdentifiers(comment, identifiers, scope); + } // var function Foo() { diff --git a/lib/is_jsdoc_comment.js b/lib/is_jsdoc_comment.js index fd5a70f32..79835a428 100644 --- a/lib/is_jsdoc_comment.js +++ b/lib/is_jsdoc_comment.js @@ -11,7 +11,7 @@ * comments. * * @name isJSDocComment - * @param {Object} comment an ast node of the comment + * @param {Object} comment an ast path of the comment * @return {boolean} whether it is valid */ module.exports = function isJSDocComment(comment/*: { diff --git a/lib/module_filters.js b/lib/module_filters.js index 6c10b1855..501d7a7d9 100644 --- a/lib/module_filters.js +++ b/lib/module_filters.js @@ -12,7 +12,6 @@ var internalModuleRegexp = process.platform === 'win32' ? /** * Module filters - * @private */ module.exports = { internalOnly: internalModuleRegexp.test.bind(internalModuleRegexp), diff --git a/lib/parsers/javascript.js b/lib/parsers/javascript.js index cd9ff2edc..3a8db26e6 100644 --- a/lib/parsers/javascript.js +++ b/lib/parsers/javascript.js @@ -45,7 +45,8 @@ function parseJavaScript(data/*: Object*/, walkComments.bind(null, 'leadingComments', true), walkComments.bind(null, 'innerComments', false), walkComments.bind(null, 'trailingComments', false) - ], fn => fn(ast, data, addComment)).filter(Boolean); + ], fn => fn(ast, data, addComment)) + .filter(comment => comment && !comment.lends); } function _addComment(visited, data, commentValue, commentLoc, path, nodeLoc, includeContext) { diff --git a/test/fixture/default-export-function.input.js b/test/fixture/default-export-function.input.js new file mode 100644 index 000000000..10741869d --- /dev/null +++ b/test/fixture/default-export-function.input.js @@ -0,0 +1,5 @@ +/** i am foo */ +export default function() { + /** i am foo's son */ + this.bar = () => { } +}; diff --git a/test/fixture/default-export-function.output.json b/test/fixture/default-export-function.output.json new file mode 100644 index 000000000..41c8774b9 --- /dev/null +++ b/test/fixture/default-export-function.output.json @@ -0,0 +1,214 @@ +[ + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "i am foo", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 9, + "offset": 8 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 9, + "offset": 8 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 9, + "offset": 8 + } + } + }, + "tags": [], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "context": { + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + } + }, + "augments": [], + "errors": [], + "examples": [], + "params": [], + "properties": [], + "returns": [], + "sees": [], + "throws": [], + "todos": [], + "name": "default-export-function.input", + "kind": "function", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "default-export-function.input", + "kind": "function" + } + ], + "namespace": "default-export-function.input" + }, + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "i am foo's son", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 15, + "offset": 14 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 15, + "offset": 14 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 15, + "offset": 14 + } + } + }, + "tags": [], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 23 + } + }, + "context": { + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 22 + } + } + }, + "augments": [], + "errors": [ + { + "message": "@memberof reference to default-export-function.input not found", + "commentLineNumber": 0 + } + ], + "examples": [], + "params": [], + "properties": [], + "returns": [], + "sees": [], + "throws": [], + "todos": [], + "name": "bar", + "kind": "function", + "memberof": "default-export-function.input", + "scope": "static", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "bar", + "kind": "function", + "scope": "static" + } + ], + "namespace": ".bar" + } +] \ No newline at end of file diff --git a/test/fixture/default-export-function.output.md b/test/fixture/default-export-function.output.md new file mode 100644 index 000000000..f5751264f --- /dev/null +++ b/test/fixture/default-export-function.output.md @@ -0,0 +1,14 @@ + + +### Table of Contents + +- [default-export-function.input](#default-export-functioninput) +- [bar](#bar) + +## default-export-function.input + +i am foo + +## bar + +i am foo's son diff --git a/test/fixture/default-export-function.output.md.json b/test/fixture/default-export-function.output.md.json new file mode 100644 index 000000000..bebb70b41 --- /dev/null +++ b/test/fixture/default-export-function.output.md.json @@ -0,0 +1,99 @@ +{ + "type": "root", + "children": [ + { + "type": "html", + "value": "" + }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "default-export-function.input" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "i am foo", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 9, + "offset": 8 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 9, + "offset": 8 + }, + "indent": [] + } + }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "bar" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "i am foo's son", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 15, + "offset": 14 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 15, + "offset": 14 + }, + "indent": [] + } + } + ] +} \ No newline at end of file diff --git a/test/fixture/document-exported-export-default-object.output.json b/test/fixture/document-exported-export-default-object.output.json index fda6f1de9..891d8bc4c 100644 --- a/test/fixture/document-exported-export-default-object.output.json +++ b/test/fixture/document-exported-export-default-object.output.json @@ -74,7 +74,12 @@ } }, "augments": [], - "errors": [], + "errors": [ + { + "message": "@memberof reference to document-exported-export-default-object.input not found", + "commentLineNumber": 0 + } + ], "examples": [], "params": [], "properties": [], @@ -83,6 +88,8 @@ "throws": [], "todos": [], "name": "x", + "memberof": "document-exported-export-default-object.input", + "scope": "static", "members": { "global": [], "inner": [], @@ -92,9 +99,10 @@ }, "path": [ { - "name": "x" + "name": "x", + "scope": "static" } ], - "namespace": "x" + "namespace": ".x" } ] \ No newline at end of file diff --git a/test/fixture/es6.input.js b/test/fixture/es6.input.js index fcef40a07..f89783c1d 100644 --- a/test/fixture/es6.input.js +++ b/test/fixture/es6.input.js @@ -158,3 +158,4 @@ export function isArrayEqualWith( ): boolean { return true; } + diff --git a/test/fixture/lends.input.js b/test/fixture/lends.input.js new file mode 100644 index 000000000..4aa9a25b7 --- /dev/null +++ b/test/fixture/lends.input.js @@ -0,0 +1,26 @@ +/** + * A neat layout view + * @class TheClass + * @augments Augmented + */ +export default TheClass( + /** @lends TheClass.prototype */ + { + /** + * My neat function + * @param {string} word your word + * @returns {string} your word but one better + */ + foo: function(word) { + return word + 1; + }, + /** + * My neat function + * @param {string} word your word + * @returns {string} your word but one better + */ + bar(word) { + return word + 1; + } + } +) diff --git a/test/fixture/lends.output.json b/test/fixture/lends.output.json new file mode 100644 index 000000000..351407dda --- /dev/null +++ b/test/fixture/lends.output.json @@ -0,0 +1,630 @@ +[ + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "A neat layout view", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 19, + "offset": 18 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 19, + "offset": 18 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 19, + "offset": 18 + } + } + }, + "tags": [ + { + "title": "class", + "description": null, + "lineNumber": 2, + "type": null, + "name": "TheClass" + }, + { + "title": "augments", + "description": null, + "lineNumber": 3, + "type": null, + "name": "Augmented" + } + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 3 + } + }, + "context": { + "loc": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 26, + "column": 1 + } + } + }, + "augments": [ + { + "title": "augments", + "description": null, + "lineNumber": 3, + "type": null, + "name": "Augmented" + } + ], + "errors": [], + "examples": [], + "params": [], + "properties": [], + "returns": [], + "sees": [], + "throws": [], + "todos": [], + "kind": "class", + "name": "TheClass", + "members": { + "global": [], + "inner": [], + "instance": [ + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "My neat function", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + } + } + }, + "tags": [ + { + "title": "param", + "description": "your word", + "lineNumber": 2, + "type": { + "type": "NameExpression", + "name": "string" + }, + "name": "word" + }, + { + "title": "returns", + "description": "your word but one better", + "lineNumber": 3, + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 13, + "column": 7 + } + }, + "context": { + "loc": { + "start": { + "line": 14, + "column": 4 + }, + "end": { + "line": 16, + "column": 5 + } + } + }, + "augments": [], + "errors": [], + "examples": [], + "params": [ + { + "title": "param", + "name": "word", + "lineNumber": 2, + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + } + } + }, + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "properties": [], + "returns": [ + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word but one better", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + } + } + }, + "title": "returns", + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "sees": [], + "throws": [], + "todos": [], + "name": "foo", + "kind": "function", + "memberof": "TheClass", + "scope": "instance", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "TheClass", + "kind": "class" + }, + { + "name": "foo", + "kind": "function", + "scope": "instance" + } + ], + "namespace": "TheClass#foo" + }, + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "My neat function", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + } + } + }, + "tags": [ + { + "title": "param", + "description": "your word", + "lineNumber": 2, + "type": { + "type": "NameExpression", + "name": "string" + }, + "name": "word" + }, + { + "title": "returns", + "description": "your word but one better", + "lineNumber": 3, + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 4 + }, + "end": { + "line": 21, + "column": 7 + } + }, + "context": { + "loc": { + "start": { + "line": 22, + "column": 4 + }, + "end": { + "line": 24, + "column": 5 + } + } + }, + "augments": [], + "errors": [], + "examples": [], + "params": [ + { + "title": "param", + "name": "word", + "lineNumber": 2, + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + } + } + }, + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "properties": [], + "returns": [ + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word but one better", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + } + } + }, + "title": "returns", + "type": { + "type": "NameExpression", + "name": "string" + } + } + ], + "sees": [], + "throws": [], + "todos": [], + "name": "bar", + "kind": "function", + "memberof": "TheClass", + "scope": "instance", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "TheClass", + "kind": "class" + }, + { + "name": "bar", + "kind": "function", + "scope": "instance" + } + ], + "namespace": "TheClass#bar" + } + ], + "events": [], + "static": [] + }, + "path": [ + { + "name": "TheClass", + "kind": "class" + } + ], + "namespace": "TheClass" + } +] \ No newline at end of file diff --git a/test/fixture/lends.output.md b/test/fixture/lends.output.md new file mode 100644 index 000000000..23ccc043c --- /dev/null +++ b/test/fixture/lends.output.md @@ -0,0 +1,33 @@ + + +### Table of Contents + +- [TheClass](#theclass) + - [foo](#foo) + - [bar](#bar) + +## TheClass + +**Extends Augmented** + +A neat layout view + +### foo + +My neat function + +**Parameters** + +- `word` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** your word + +Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** your word but one better + +### bar + +My neat function + +**Parameters** + +- `word` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** your word + +Returns **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** your word but one better diff --git a/test/fixture/lends.output.md.json b/test/fixture/lends.output.md.json new file mode 100644 index 000000000..03620a2fe --- /dev/null +++ b/test/fixture/lends.output.md.json @@ -0,0 +1,466 @@ +{ + "type": "root", + "children": [ + { + "type": "html", + "value": "" + }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "TheClass" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Extends " + }, + { + "type": "text", + "value": "Augmented" + } + ] + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "A neat layout view", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 19, + "offset": 18 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 19, + "offset": 18 + }, + "indent": [] + } + }, + { + "depth": 3, + "type": "heading", + "children": [ + { + "type": "text", + "value": "foo" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "My neat function", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Parameters" + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "word" + }, + { + "type": "text", + "value": " " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "type": "link", + "children": [ + { + "type": "text", + "value": "string" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ] + } + ] + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Returns " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "type": "link", + "children": [ + { + "type": "text", + "value": "string" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word but one better", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ] + }, + { + "depth": 3, + "type": "heading", + "children": [ + { + "type": "text", + "value": "bar" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "My neat function", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 17, + "offset": 16 + }, + "indent": [] + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Parameters" + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "word" + }, + { + "type": "text", + "value": " " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "type": "link", + "children": [ + { + "type": "text", + "value": "string" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 10, + "offset": 9 + }, + "indent": [] + } + } + ] + } + ] + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Returns " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String", + "type": "link", + "children": [ + { + "type": "text", + "value": "string" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "your word but one better", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 25, + "offset": 24 + }, + "indent": [] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test/lib/infer/membership.js b/test/lib/infer/membership.js index 373230b68..bd7d35165 100644 --- a/test/lib/infer/membership.js +++ b/test/lib/infer/membership.js @@ -209,7 +209,7 @@ test('inferMembership - explicit', function (t) { /** Test */ bar: 0 }); - })[1], ['memberof', 'scope']), { + })[0], ['memberof', 'scope']), { memberof: 'Foo', scope: 'static' }, 'lends, static'); @@ -219,7 +219,7 @@ test('inferMembership - explicit', function (t) { /** Test */ bar: function () {} }); - })[1], ['memberof', 'scope']), { + })[0], ['memberof', 'scope']), { memberof: 'Foo', scope: 'static' }, 'inferMembership - lends, static, function'); @@ -229,7 +229,7 @@ test('inferMembership - explicit', function (t) { /** Test */ bar: 0 }); - })[1], ['memberof', 'scope']), { + })[0], ['memberof', 'scope']), { memberof: 'Foo', scope: 'instance' }); @@ -239,7 +239,7 @@ test('inferMembership - explicit', function (t) { /** Test */ bar: function () {} }); - })[1], ['memberof', 'scope']), { + })[0], ['memberof', 'scope']), { memberof: 'Foo', scope: 'instance' }, 'inferMembership - lends, instance, function'); @@ -261,11 +261,7 @@ test('inferMembership - explicit', function (t) { t.equal(evaluate(function () { lend(/** @lends Foo */{}); /** Test */ - })[1].memberof, undefined, 'inferMembership - lends applies only to following object'); - - t.equal(evaluate(function () { - lend(/** @lends Foo */{}); - })[0].memberof, undefined, 'inferMembership - drops lends'); + })[0].memberof, undefined, 'inferMembership - lends applies only to following object'); t.end(); }); diff --git a/test/lib/parse.js b/test/lib/parse.js index aef852939..5bde5893f 100644 --- a/test/lib/parse.js +++ b/test/lib/parse.js @@ -454,14 +454,6 @@ test('parse - @kind', function (t) { t.end(); }); -test('parse - @lends', function (t) { - t.equal(evaluate(function () { - /** @lends lendee */ - })[0].lends, 'lendee', 'lends'); - - t.end(); -}); - test('parse - @license', function (t) { t.end(); });