From d6dec61783b0cf264ffc34b97e6cc7776e496736 Mon Sep 17 00:00:00 2001 From: Tom Macwright Date: Mon, 24 Apr 2017 20:43:25 -0400 Subject: [PATCH] feat(params): Support inline parameter documentation This allows users to add comments within destructuring patterns, ObjectPattern and ArrayPattern, that add documentation for specific parameters. Fixes #29 --- lib/extractors/comments.js | 4 +- lib/infer/params.js | 26 +- test/fixture/params.input.js | 10 + test/fixture/params.output.json | 369 +++++++++++++++++++++++++---- test/fixture/params.output.md | 16 ++ test/fixture/params.output.md.json | 228 ++++++++++++++++++ 6 files changed, 607 insertions(+), 46 deletions(-) diff --git a/lib/extractors/comments.js b/lib/extractors/comments.js index f6e4abaf7..7d6baf451 100644 --- a/lib/extractors/comments.js +++ b/lib/extractors/comments.js @@ -51,7 +51,9 @@ function walkComments( ); } - (path.node[type] || []).filter(isJSDocComment).forEach(parseComment); + if (path.node[type]) { + path.node[type].filter(isJSDocComment).forEach(parseComment); + } } }); diff --git a/lib/infer/params.js b/lib/infer/params.js index dd92bad1b..78bbe97de 100644 --- a/lib/infer/params.js +++ b/lib/infer/params.js @@ -8,6 +8,20 @@ const findTarget = require('./finders').findTarget; const flowDoctrine = require('../flow_doctrine'); const util = require('util'); const debuglog = util.debuglog('documentation'); +const parseJSDoc = require('../parse'); +const isJSDocComment = require('../is_jsdoc_comment'); + +function getInlineDescription(param) { + if (param.trailingComments && isJSDocComment(param.trailingComments[0])) { + var parsedInlineComment = parseJSDoc(param.trailingComments[0].value); + if (parsedInlineComment && parsedInlineComment.description) { + return { + description: parsedInlineComment.description + }; + } + } + return {}; +} /** * Infers param tags by reading function parameter names @@ -182,9 +196,13 @@ function paramToDoc( return paramToDoc(indexedElement, prefix); }); case 'ObjectProperty': - return _.assign(paramToDoc(param.value, prefix + '.' + param.key.name), { - name: prefix + '.' + param.key.name - }); + return _.assign( + paramToDoc(param.value, prefix + '.' + param.key.name), + { + name: prefix + '.' + param.key.name + }, + getInlineDescription(param) + ); case 'RestProperty': // (a, ...b) case 'RestElement': let type /*: DoctrineType */ = { @@ -213,7 +231,7 @@ function paramToDoc( newParam.type = flowDoctrine(param.typeAnnotation.typeAnnotation); } - return newParam; + return _.assign(newParam, getInlineDescription(param)); } } diff --git a/test/fixture/params.input.js b/test/fixture/params.input.js index 50e7b514e..c6f143b60 100644 --- a/test/fixture/params.input.js +++ b/test/fixture/params.input.js @@ -15,6 +15,16 @@ function fishesAndFoxes({ fishes, foxes }) { return fishes + foxes; } +/** + * This method has inline documentation for a param + * @param {Object} options + */ +function fishesAndFoxesInline( + { fishes /** number of kinds of fish */, foxes } +) { + return fishes + foxes; +} + /** * This method has a type in the description and a default in the code * @param {number} x diff --git a/test/fixture/params.output.json b/test/fixture/params.output.json index 129cc02b3..f27425213 100644 --- a/test/fixture/params.output.json +++ b/test/fixture/params.output.json @@ -411,6 +411,293 @@ ], "namespace": "fishesAndFoxes" }, + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "This method has inline documentation for a param", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 49, + "offset": 48 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 49, + "offset": 48 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 49, + "offset": 48 + } + } + }, + "tags": [ + { + "title": "param", + "description": null, + "lineNumber": 2, + "type": { + "type": "NameExpression", + "name": "Object" + }, + "name": "options" + } + ], + "loc": { + "start": { + "line": 18, + "column": 0 + }, + "end": { + "line": 21, + "column": 3 + } + }, + "context": { + "loc": { + "start": { + "line": 22, + "column": 0 + }, + "end": { + "line": 26, + "column": 1 + } + } + }, + "augments": [], + "errors": [], + "examples": [], + "params": [ + { + "title": "param", + "name": "options", + "lineNumber": 2, + "type": { + "type": "NameExpression", + "name": "Object" + }, + "properties": [ + { + "title": "param", + "name": "options.fishes", + "lineNumber": 23, + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "number of kinds of fish", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + } + } + } + }, + { + "title": "param", + "name": "options.foxes", + "lineNumber": 23 + } + ] + } + ], + "properties": [], + "returns": [], + "sees": [], + "throws": [], + "todos": [], + "name": "fishesAndFoxesInline", + "kind": "function", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "fishesAndFoxesInline", + "kind": "function" + } + ], + "namespace": "fishesAndFoxesInline" + }, + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "number of kinds of fish", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + } + } + }, + "tags": [], + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 41 + } + }, + "context": { + "loc": { + "start": { + "line": 23, + "column": 43 + }, + "end": { + "line": 23, + "column": 48 + } + } + }, + "augments": [], + "errors": [], + "examples": [], + "params": [], + "properties": [], + "returns": [], + "sees": [], + "throws": [], + "todos": [], + "name": "foxes", + "members": { + "global": [], + "inner": [], + "instance": [], + "events": [], + "static": [] + }, + "path": [ + { + "name": "foxes" + } + ], + "namespace": "foxes" + }, { "description": { "type": "root", @@ -478,22 +765,22 @@ ], "loc": { "start": { - "line": 18, + "line": 28, "column": 0 }, "end": { - "line": 21, + "line": 31, "column": 3 } }, "context": { "loc": { "start": { - "line": 22, + "line": 32, "column": 0 }, "end": { - "line": 24, + "line": 34, "column": 1 } } @@ -594,22 +881,22 @@ "tags": [], "loc": { "start": { - "line": 26, + "line": 36, "column": 0 }, "end": { - "line": 28, + "line": 38, "column": 3 } }, "context": { "loc": { "start": { - "line": 29, + "line": 39, "column": 0 }, "end": { - "line": 35, + "line": 45, "column": 1 } } @@ -696,22 +983,22 @@ ], "loc": { "start": { - "line": 30, + "line": 40, "column": 2 }, "end": { - "line": 33, + "line": 43, "column": 5 } }, "context": { "loc": { "start": { - "line": 34, + "line": 44, "column": 2 }, "end": { - "line": 34, + "line": 44, "column": 14 } } @@ -879,22 +1166,22 @@ "tags": [], "loc": { "start": { - "line": 37, + "line": 47, "column": 0 }, "end": { - "line": 39, + "line": 49, "column": 3 } }, "context": { "loc": { "start": { - "line": 40, + "line": 50, "column": 0 }, "end": { - "line": 47, + "line": 57, "column": 2 } } @@ -971,22 +1258,22 @@ "tags": [], "loc": { "start": { - "line": 41, + "line": 51, "column": 2 }, "end": { - "line": 43, + "line": 53, "column": 5 } }, "context": { "loc": { "start": { - "line": 44, + "line": 54, "column": 2 }, "end": { - "line": 46, + "line": 56, "column": 3 } } @@ -998,7 +1285,7 @@ { "title": "param", "name": "x", - "lineNumber": 44 + "lineNumber": 54 } ], "properties": [], @@ -1194,22 +1481,22 @@ ], "loc": { "start": { - "line": 49, + "line": 59, "column": 0 }, "end": { - "line": 60, + "line": 70, "column": 3 } }, "context": { "loc": { "start": { - "line": 61, + "line": 71, "column": 0 }, "end": { - "line": 61, + "line": 71, "column": 22 } } @@ -1672,22 +1959,22 @@ ], "loc": { "start": { - "line": 63, + "line": 73, "column": 0 }, "end": { - "line": 74, + "line": 84, "column": 3 } }, "context": { "loc": { "start": { - "line": 75, + "line": 85, "column": 0 }, "end": { - "line": 77, + "line": 87, "column": 1 } } @@ -2132,22 +2419,22 @@ ], "loc": { "start": { - "line": 79, + "line": 89, "column": 0 }, "end": { - "line": 86, + "line": 96, "column": 3 } }, "context": { "loc": { "start": { - "line": 87, + "line": 97, "column": 0 }, "end": { - "line": 87, + "line": 97, "column": 37 } } @@ -2372,22 +2659,22 @@ ], "loc": { "start": { - "line": 89, + "line": 99, "column": 0 }, "end": { - "line": 94, + "line": 104, "column": 3 } }, "context": { "loc": { "start": { - "line": 95, + "line": 105, "column": 0 }, "end": { - "line": 97, + "line": 107, "column": 1 } } @@ -2588,22 +2875,22 @@ ], "loc": { "start": { - "line": 99, + "line": 109, "column": 0 }, "end": { - "line": 108, + "line": 118, "column": 3 } }, "context": { "loc": { "start": { - "line": 109, + "line": 119, "column": 0 }, "end": { - "line": 111, + "line": 121, "column": 1 } } diff --git a/test/fixture/params.output.md b/test/fixture/params.output.md index 6413e14bf..e26ecd6b4 100644 --- a/test/fixture/params.output.md +++ b/test/fixture/params.output.md @@ -4,6 +4,8 @@ - [addThem](#addthem) - [fishesAndFoxes](#fishesandfoxes) +- [fishesAndFoxesInline](#fishesandfoxesinline) +- [foxes](#foxes) - [withDefault](#withdefault) - [Foo](#foo) - [method](#method) @@ -39,6 +41,20 @@ This method has partially inferred params - `options.fishes` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** number of kinds of fish - `options.foxes` +## fishesAndFoxesInline + +This method has inline documentation for a param + +**Parameters** + +- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** + - `options.fishes` number of kinds of fish + - `options.foxes` + +## foxes + +number of kinds of fish + ## withDefault This method has a type in the description and a default in the code diff --git a/test/fixture/params.output.md.json b/test/fixture/params.output.md.json index 69f263493..1405232c2 100644 --- a/test/fixture/params.output.md.json +++ b/test/fixture/params.output.md.json @@ -491,6 +491,234 @@ } ] }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "fishesAndFoxesInline" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "This method has inline documentation for a param", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 49, + "offset": 48 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 49, + "offset": 48 + }, + "indent": [] + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Parameters" + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "options" + }, + { + "type": "text", + "value": " " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object", + "type": "link", + "children": [ + { + "type": "text", + "value": "Object" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "options.fishes" + }, + { + "type": "text", + "value": " " + }, + { + "type": "text", + "value": " " + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "number of kinds of fish", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ] + } + ] + }, + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "options.foxes" + }, + { + "type": "text", + "value": " " + }, + { + "type": "text", + "value": " " + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "foxes" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "number of kinds of fish", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 24, + "offset": 23 + }, + "indent": [] + } + }, { "depth": 2, "type": "heading",