Skip to content

Commit

Permalink
fix: Infer parameters for classes from constructors
Browse files Browse the repository at this point in the history
Fixes #689
  • Loading branch information
tmcw committed Apr 24, 2017
1 parent 7c00acc commit 355038d
Show file tree
Hide file tree
Showing 12 changed files with 780 additions and 652 deletions.
39 changes: 39 additions & 0 deletions docs/RECIPES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
## Classes

ES6 has a nice, formal way of declaring classes. documentation.js handles it well:
here are tips for dealing with them.

**Document constructor parameters with the class, not the constructor method.**

Do:

```js
/**
* A table object
* @param {number} width
* @param {number} height
*/
class Table {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
```

Don't:

```js
/** A table object */
class Table {
/*
* @param {number} width
* @param {number} height
*/
constructor(width, height) {
this.width = width;
this.height = height;
}
}
```

## Destructuring Parameters

In ES6, you can use [destructuring assignment in functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment):
Expand Down
20 changes: 17 additions & 3 deletions lib/infer/params.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const _ = require('lodash');
const findTarget = require('./finders').findTarget;
const flowDoctrine = require('../flow_doctrine');
const util = require('util');
const debuglog = util.debuglog('infer');
const debuglog = util.debuglog('documentation');

/**
* Infers param tags by reading function parameter names
Expand All @@ -24,13 +24,27 @@ function inferParams(comment /*: Comment */) {
path = path.get('init');
}

// If this is an ES6 class with a constructor method, infer
// parameters from that constructor method.
if (t.isClassDeclaration(path)) {
let constructor = path.node.body.body.find(item => {
// https://github.com/babel/babylon/blob/master/ast/spec.md#classbody
return t.isClassMethod(item) && item.kind === 'constructor';
});
if (constructor) {
return inferAndCombineParams(constructor.params, comment);
}
}

if (!t.isFunction(path)) {
return comment;
}

var inferredParams = path.node.params.map((param, i) =>
paramToDoc(param, '', i));
return inferAndCombineParams(path.node.params, comment);
}

function inferAndCombineParams(params, comment) {
var inferredParams = params.map((param, i) => paramToDoc(param, '', i));
var mergedParams = mergeTrees(inferredParams, comment.params);

// Then merge the trees. This is the hard part.
Expand Down
10 changes: 10 additions & 0 deletions lib/parsers/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
/* @flow */

var _ = require('lodash'),
t = require('babel-types'),
parse = require('../../lib/parse'),
walkComments = require('../extractors/comments'),
walkExported = require('../extractors/exported'),
util = require('util'),
debuglog = util.debuglog('documentation'),
parseToAst = require('./parse_to_ast');

/**
Expand Down Expand Up @@ -89,6 +92,13 @@ function _addComment(
value: path
});

// #689
if (t.isClassMethod(path) && path.node.kind === 'constructor') {
debuglog(
'A constructor was documented explicitly: document along with the class instead'
);
}

if (path.parentPath && path.parentPath.node) {
var parentNode = path.parentPath.node;
context.code = data.source.substring(parentNode.start, parentNode.end);
Expand Down
20 changes: 12 additions & 8 deletions test/fixture/es6-class.input.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ class Foo extends React.Component {}

/**
* Does nothing. This is from issue #556
* @param {string} str
*/
export default class Bar {
/**
* Creates a new instance
* @param {string} str
*/
export class Bar {
constructor(str) {
/**
* A useless property
* @type {string}
*/
* A useless property
* @type {string}
*/
this.bar = '';
}
}

/**
* This class has fully inferred constructor parameters.
*/
export class Baz {
constructor(n: number, l: Array<string>) {}
}
Loading

0 comments on commit 355038d

Please sign in to comment.