Skip to content

Commit 7e7a17c

Browse files
committed
Handle assignments in document exported
This improves detection of cases where we have: ```js export const f = function () {}; export const o = { ... }; ``` and similarly indirection using default/named. ```js const f = function () {}; export {f}; ``` Fixes documentationjs#543
1 parent 2eff668 commit 7e7a17c

10 files changed

+487
-40
lines changed

lib/extractors/exported.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ var traverse = require('babel-traverse').default,
33
t = require('babel-types'),
44
nodePath = require('path'),
55
fs = require('fs'),
6-
parseToAst = require('../parsers/parse_to_ast');
6+
parseToAst = require('../parsers/parse_to_ast'),
7+
findTarget = require('../infer/finders').findTarget;
78

89
/**
910
* Iterate through the abstract syntax tree, finding ES6-style exports,
@@ -52,14 +53,18 @@ function walkExported(ast, data, addComment) {
5253
var declaration = path.get('declaration');
5354
if (t.isDeclaration(declaration)) {
5455
traverseExportedSubtree(declaration, data, addComments);
56+
return path.skip();
5557
}
5658

5759
if (path.isExportDefaultDeclaration()) {
5860
if (declaration.isDeclaration()) {
5961
traverseExportedSubtree(declaration, data, addComments);
60-
} else if (declaration.isIdentifier()) {
62+
return path.skip();
63+
}
64+
if (declaration.isIdentifier()) {
6165
var binding = declaration.scope.getBinding(declaration.node.name);
6266
traverseExportedSubtree(binding.path, data, addComments);
67+
return path.skip();
6368
}
6469
}
6570

@@ -92,6 +97,7 @@ function walkExported(ast, data, addComment) {
9297

9398
traverseExportedSubtree(bindingPath, specData, addComments, exported);
9499
});
100+
return path.skip();
95101
}
96102
}
97103
});
@@ -110,12 +116,10 @@ function traverseExportedSubtree(path, data, addComments, overrideName) {
110116
}
111117
addComments(data, attachCommentPath, overrideName);
112118

113-
if (path.isVariableDeclaration()) {
114-
// TODO: How does JSDoc handle multiple declarations?
115-
path = path.get('declarations')[0].get('init');
116-
if (!path) {
117-
return;
118-
}
119+
path = findTarget(path);
120+
121+
if (t.isVariableDeclarator(path) && path.has('init')) {
122+
path = path.get('init');
119123
}
120124

121125
if (path.isClass() || path.isObjectExpression()) {

lib/infer/augments.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

33
var shouldSkipInference = require('./should_skip_inference'),
4-
finders = require('./finders');
4+
findClass = require('./finders').findClass;
55

66
/**
77
* Infers an `augments` tag from an ES6 class declaration
@@ -15,12 +15,12 @@ function inferAugments() {
1515
return comment;
1616
}
1717

18-
var node = finders.findClass(comment.context.ast);
18+
var path = findClass(comment.context.ast);
1919

20-
if (node && node.superClass) {
20+
if (path && path.node.superClass) {
2121
comment.augments = [{
2222
title: 'augments',
23-
name: node.superClass.name
23+
name: path.node.superClass.name
2424
}];
2525
}
2626

lib/infer/finders.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,50 @@
1+
'use strict';
2+
13
var t = require('babel-types');
24

35
/**
46
* Try to find the part of JavaScript a comment is referring to, by
57
* looking at the syntax tree closest to that comment.
68
*
79
* @param {Object} path abstract syntax tree path
8-
* @returns {?Object} ast node, if one is found.
10+
* @returns {?Object} ast path, if one is found.
911
* @private
1012
*/
1113
function findTarget(path) {
12-
1314
if (!path) {
1415
return path;
1516
}
1617

17-
if (path.node) {
18-
path = path.node;
19-
}
20-
21-
if (t.isExportNamedDeclaration(path) || t.isExportDefaultDeclaration(path)) {
22-
path = path.declaration;
18+
if (t.isExportDefaultDeclaration(path) ||
19+
t.isExportNamedDeclaration(path) && path.has('declaration')) {
20+
path = path.get('declaration');
2321
}
2422

2523
// var x = init;
2624
if (t.isVariableDeclaration(path)) {
27-
return path.declarations[0];
28-
}
25+
path = path.get('declarations')[0];
2926

3027
// foo.x = TARGET
31-
if (t.isExpressionStatement(path)) {
32-
return path.expression.right;
28+
} else if (t.isExpressionStatement(path)) {
29+
path = path.get('expression').get('right');
3330
}
3431

35-
return path;
32+
return path.node && path;
3633
}
3734

3835
/**
3936
* Try to find a JavaScript class that this comment refers to,
4037
* whether an expression in an assignment, or a declaration.
4138
*
42-
* @param {Object} node abstract syntax tree node
43-
* @returns {?Object} ast node, if one is found.
39+
* @param {Object} path abstract syntax tree path
40+
* @returns {?Object} ast path, if one is found.
4441
* @private
4542
*/
46-
function findClass(node) {
47-
var target = findTarget(node);
48-
return (t.isClassDeclaration(target) || t.isClassExpression(target)) && target;
43+
function findClass(path) {
44+
var target = findTarget(path);
45+
if (target && (target.isClassDeclaration() || target.isClassExpression())) {
46+
return target;
47+
}
4948
}
5049

5150
module.exports.findTarget = findTarget;

lib/infer/params.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
var shouldSkipInference = require('./should_skip_inference'),
44
t = require('babel-types'),
5-
finders = require('./finders'),
5+
findTarget = require('./finders').findTarget,
66
flowDoctrine = require('../flow_doctrine');
77

88
/**
@@ -160,15 +160,15 @@ function paramToDoc(param, comment, i, prefix) {
160160
*/
161161
function inferParams() {
162162
return shouldSkipInference(function inferParams(comment) {
163-
var node = finders.findTarget(comment.context.ast);
163+
var path = findTarget(comment.context.ast);
164164

165165
// In case of `/** */ var x = function () {}` findTarget returns
166166
// the declarator.
167-
if (t.isVariableDeclarator(node)) {
168-
node = node.init;
167+
if (t.isVariableDeclarator(path)) {
168+
path = path.get('init');
169169
}
170170

171-
if (!t.isFunction(node)) {
171+
if (!t.isFunction(path)) {
172172
return comment;
173173
}
174174

@@ -182,7 +182,7 @@ function inferParams() {
182182
var paramOrder = {};
183183
var i = 0;
184184

185-
node.params
185+
path.node.params
186186
.reduce(function (params, param, i) {
187187
return params.concat(paramToDoc(param, comment, i));
188188
}, [])

lib/infer/return.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ module.exports = function () {
1717
if (comment.returns) {
1818
return comment;
1919
}
20-
var fn = finders.findTarget(comment.context.ast);
20+
var path = finders.findTarget(comment.context.ast);
21+
var fn = path && path.node;
2122
if (t.isFunction(fn) &&
2223
fn.returnType &&
2324
fn.returnType.typeAnnotation) {

lib/infer/type.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var finders = require('./finders'),
3+
var findTarget = require('./finders').findTarget,
44
shouldSkipInference = require('./should_skip_inference'),
55
flowDoctrine = require('../flow_doctrine'),
66
t = require('babel-types');
@@ -24,11 +24,12 @@ module.exports = function () {
2424
return comment;
2525
}
2626

27-
var n = finders.findTarget(comment.context.ast);
28-
if (!n) {
27+
var path = findTarget(comment.context.ast);
28+
if (!path) {
2929
return comment;
3030
}
3131

32+
var n = path.node;
3233
var type;
3334
switch (n.type) {
3435
case 'VariableDeclarator':

test/fixture/document-exported.input.js

+14
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,17 @@ type T3 = string;
6363
export type {T2, T3 as T4};
6464

6565
export type {T5} from './document-exported/x.js';
66+
67+
export var f4 = function(x: X) {}
68+
69+
var f5 = function(y: Y) {}
70+
export {f5};
71+
72+
export var o1 = {
73+
om1() {}
74+
}
75+
76+
var o2 = {
77+
om2() {}
78+
}
79+
export {o2};

0 commit comments

Comments
 (0)