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(); }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy