Skip to content

Commit 0a122b5

Browse files
committed
Walk trailing comments. Fixes #93
cc @jfirebaugh for the review
1 parent 1e8f0e8 commit 0a122b5

File tree

6 files changed

+615
-30
lines changed

6 files changed

+615
-30
lines changed

lib/parsers/javascript.js

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -84,42 +84,56 @@ module.exports = function (data) {
8484
var code = commentShebang(data.source),
8585
ast = espree.parse(code, espreeConfig);
8686

87-
types.visit(ast, {
88-
visitNode: function (path) {
89-
/**
90-
* Parse a comment with doctrine and decorate the result with file position and code context.
91-
*
92-
* @param {Object} comment the current state of the parsed JSDoc comment
93-
* @return {undefined} this emits data
94-
*/
95-
function parseComment(comment) {
96-
var context = {
97-
loc: extend({}, path.value.loc),
98-
file: data.file
99-
};
87+
var visited = {};
10088

101-
// This is non-enumerable so that it doesn't get stringified in output; e.g. by the
102-
// documentation binary.
103-
Object.defineProperty(context, 'ast', {
104-
enumerable: false,
105-
value: path
106-
});
89+
function walkComments(ast, type) {
90+
types.visit(ast, {
91+
visitNode: function (path) {
92+
/**
93+
* Parse a comment with doctrine and decorate the result with file position and code context.
94+
*
95+
* @param {Object} comment the current state of the parsed JSDoc comment
96+
* @return {undefined} this emits data
97+
*/
98+
function parseComment(comment) {
99+
var context = {
100+
loc: extend({}, path.value.loc),
101+
file: data.file
102+
};
103+
var key = JSON.stringify(comment.loc);
107104

108-
if (path.parent && path.parent.node) {
109-
context.code = code.substring
110-
.apply(code, path.parent.node.range);
105+
if (visited[key]) {
106+
return;
107+
}
108+
109+
visited[key] = true;
110+
111+
// This is non-enumerable so that it doesn't get stringified in output; e.g. by the
112+
// documentation binary.
113+
Object.defineProperty(context, 'ast', {
114+
enumerable: false,
115+
value: path
116+
});
117+
118+
if (path.parent && path.parent.node) {
119+
context.code = code.substring
120+
.apply(code, path.parent.node.range);
121+
}
122+
123+
results.push(parse(comment.value, comment.loc, context));
111124
}
112125

113-
results.push(parse(comment.value, comment.loc, context));
114-
}
126+
(path.value[type] || [])
127+
.filter(isJSDocComment)
128+
.forEach(parseComment);
115129

116-
(path.value.leadingComments || [])
117-
.filter(isJSDocComment)
118-
.forEach(parseComment);
130+
this.traverse(path);
131+
}
132+
});
133+
}
119134

120-
this.traverse(path);
121-
}
122-
});
135+
walkComments(ast, 'leadingComments');
136+
walkComments(ast, 'trailingComments');
123137

124138
return results;
125139
};

test/fixture/trailing.input.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* ONE
3+
* @return {number} something
4+
*/
5+
function fooBar() {
6+
return 1;
7+
}
8+
/**
9+
* TWO
10+
* @return {number} something
11+
*/
12+
function fooBaz() {
13+
return 2;
14+
}
15+
/**
16+
* this is a type
17+
* @class Something
18+
*/
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Something
2+
3+
this is a type
4+
5+
6+
7+
# fooBar
8+
9+
ONE
10+
11+
12+
Returns **number** something
13+
14+
15+
16+
17+
# fooBaz
18+
19+
TWO
20+
21+
22+
Returns **number** something
23+
24+
25+

test/fixture/trailing.output.json

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
[
2+
{
3+
"description": "this is a type",
4+
"tags": [
5+
{
6+
"title": "class",
7+
"description": null,
8+
"lineNumber": 2,
9+
"type": null,
10+
"name": "Something"
11+
}
12+
],
13+
"loc": {
14+
"start": {
15+
"line": 15,
16+
"column": 0
17+
},
18+
"end": {
19+
"line": 18,
20+
"column": 3
21+
}
22+
},
23+
"context": {
24+
"loc": {
25+
"start": {
26+
"line": 12,
27+
"column": 0
28+
},
29+
"end": {
30+
"line": 14,
31+
"column": 1
32+
}
33+
},
34+
"code": "function fooBar() {\n return 1;\n}\n/**\n * TWO\n * @return {number} something\n */\nfunction fooBaz() {\n return 2;\n}"
35+
},
36+
"errors": [],
37+
"class": {
38+
"name": "Something"
39+
},
40+
"name": "Something",
41+
"kind": "class",
42+
"members": {
43+
"instance": [],
44+
"static": []
45+
},
46+
"events": [],
47+
"path": [
48+
"Something"
49+
]
50+
},
51+
{
52+
"description": "ONE",
53+
"tags": [
54+
{
55+
"title": "returns",
56+
"description": "something",
57+
"lineNumber": 2,
58+
"type": {
59+
"type": "NameExpression",
60+
"name": "number"
61+
}
62+
}
63+
],
64+
"loc": {
65+
"start": {
66+
"line": 1,
67+
"column": 0
68+
},
69+
"end": {
70+
"line": 4,
71+
"column": 3
72+
}
73+
},
74+
"context": {
75+
"loc": {
76+
"start": {
77+
"line": 5,
78+
"column": 0
79+
},
80+
"end": {
81+
"line": 7,
82+
"column": 1
83+
}
84+
},
85+
"code": "function fooBar() {\n return 1;\n}\n/**\n * TWO\n * @return {number} something\n */\nfunction fooBaz() {\n return 2;\n}"
86+
},
87+
"errors": [],
88+
"returns": [
89+
{
90+
"title": "returns",
91+
"description": "something",
92+
"lineNumber": 2,
93+
"type": {
94+
"type": "NameExpression",
95+
"name": "number"
96+
}
97+
}
98+
],
99+
"name": "fooBar",
100+
"kind": "function",
101+
"members": {
102+
"instance": [],
103+
"static": []
104+
},
105+
"events": [],
106+
"path": [
107+
"fooBar"
108+
]
109+
},
110+
{
111+
"description": "TWO",
112+
"tags": [
113+
{
114+
"title": "returns",
115+
"description": "something",
116+
"lineNumber": 2,
117+
"type": {
118+
"type": "NameExpression",
119+
"name": "number"
120+
}
121+
}
122+
],
123+
"loc": {
124+
"start": {
125+
"line": 8,
126+
"column": 0
127+
},
128+
"end": {
129+
"line": 11,
130+
"column": 3
131+
}
132+
},
133+
"context": {
134+
"loc": {
135+
"start": {
136+
"line": 12,
137+
"column": 0
138+
},
139+
"end": {
140+
"line": 14,
141+
"column": 1
142+
}
143+
},
144+
"code": "function fooBar() {\n return 1;\n}\n/**\n * TWO\n * @return {number} something\n */\nfunction fooBaz() {\n return 2;\n}"
145+
},
146+
"errors": [],
147+
"returns": [
148+
{
149+
"title": "returns",
150+
"description": "something",
151+
"lineNumber": 2,
152+
"type": {
153+
"type": "NameExpression",
154+
"name": "number"
155+
}
156+
}
157+
],
158+
"name": "fooBaz",
159+
"kind": "function",
160+
"members": {
161+
"instance": [],
162+
"static": []
163+
},
164+
"events": [],
165+
"path": [
166+
"fooBaz"
167+
]
168+
}
169+
]

test/fixture/trailing.output.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Something
2+
3+
this is a type
4+
5+
6+
7+
# fooBar
8+
9+
ONE
10+
11+
12+
Returns **number** something
13+
14+
15+
16+
17+
# fooBaz
18+
19+
TWO
20+
21+
22+
Returns **number** something
23+
24+
25+

0 commit comments

Comments
 (0)