Skip to content

Commit 355038d

Browse files
committed
fix: Infer parameters for classes from constructors
Fixes #689
1 parent 7c00acc commit 355038d

12 files changed

+780
-652
lines changed

docs/RECIPES.md

+39
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,42 @@
1+
## Classes
2+
3+
ES6 has a nice, formal way of declaring classes. documentation.js handles it well:
4+
here are tips for dealing with them.
5+
6+
**Document constructor parameters with the class, not the constructor method.**
7+
8+
Do:
9+
10+
```js
11+
/**
12+
* A table object
13+
* @param {number} width
14+
* @param {number} height
15+
*/
16+
class Table {
17+
constructor(width, height) {
18+
this.width = width;
19+
this.height = height;
20+
}
21+
}
22+
```
23+
24+
Don't:
25+
26+
```js
27+
/** A table object */
28+
class Table {
29+
/*
30+
* @param {number} width
31+
* @param {number} height
32+
*/
33+
constructor(width, height) {
34+
this.width = width;
35+
this.height = height;
36+
}
37+
}
38+
```
39+
140
## Destructuring Parameters
241

342
In ES6, you can use [destructuring assignment in functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment):

lib/infer/params.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const _ = require('lodash');
77
const findTarget = require('./finders').findTarget;
88
const flowDoctrine = require('../flow_doctrine');
99
const util = require('util');
10-
const debuglog = util.debuglog('infer');
10+
const debuglog = util.debuglog('documentation');
1111

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

27+
// If this is an ES6 class with a constructor method, infer
28+
// parameters from that constructor method.
29+
if (t.isClassDeclaration(path)) {
30+
let constructor = path.node.body.body.find(item => {
31+
// https://github.com/babel/babylon/blob/master/ast/spec.md#classbody
32+
return t.isClassMethod(item) && item.kind === 'constructor';
33+
});
34+
if (constructor) {
35+
return inferAndCombineParams(constructor.params, comment);
36+
}
37+
}
38+
2739
if (!t.isFunction(path)) {
2840
return comment;
2941
}
3042

31-
var inferredParams = path.node.params.map((param, i) =>
32-
paramToDoc(param, '', i));
43+
return inferAndCombineParams(path.node.params, comment);
44+
}
3345

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

3650
// Then merge the trees. This is the hard part.

lib/parsers/javascript.js

+10
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
/* @flow */
33

44
var _ = require('lodash'),
5+
t = require('babel-types'),
56
parse = require('../../lib/parse'),
67
walkComments = require('../extractors/comments'),
78
walkExported = require('../extractors/exported'),
9+
util = require('util'),
10+
debuglog = util.debuglog('documentation'),
811
parseToAst = require('./parse_to_ast');
912

1013
/**
@@ -89,6 +92,13 @@ function _addComment(
8992
value: path
9093
});
9194

95+
// #689
96+
if (t.isClassMethod(path) && path.node.kind === 'constructor') {
97+
debuglog(
98+
'A constructor was documented explicitly: document along with the class instead'
99+
);
100+
}
101+
92102
if (path.parentPath && path.parentPath.node) {
93103
var parentNode = path.parentPath.node;
94104
context.code = data.source.substring(parentNode.start, parentNode.end);

test/fixture/es6-class.input.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@ class Foo extends React.Component {}
55

66
/**
77
* Does nothing. This is from issue #556
8+
* @param {string} str
89
*/
9-
export default class Bar {
10-
/**
11-
* Creates a new instance
12-
* @param {string} str
13-
*/
10+
export class Bar {
1411
constructor(str) {
1512
/**
16-
* A useless property
17-
* @type {string}
18-
*/
13+
* A useless property
14+
* @type {string}
15+
*/
1916
this.bar = '';
2017
}
2118
}
19+
20+
/**
21+
* This class has fully inferred constructor parameters.
22+
*/
23+
export class Baz {
24+
constructor(n: number, l: Array<string>) {}
25+
}

0 commit comments

Comments
 (0)