Proposal: deprecate `sourceCode.getComments()` in favor of `sourceCode.getCommentsBefore|After|Inside`.
See original GitHub issueNow that we’re preparing for v4 in earnest and https://github.com/eslint/eslint/pull/7516 is about to land, I’d like to discuss officially deprecating sourceCode.getComments()
, as mentioned in this comment.
Now that we’re no longer relying on parsers to attach comments to nodes, I think it makes much more sense to think of comments in terms of token lists rather than the AST. The concept of attaching comments to nodes is confusing (it would be perfectly acceptable if comments could only occur between Nodes, but unfortunately comments can occur anywhere), and now that we have alternatives to this behavior (with our new token iterator methods and comment calculation moving to core), I think it would make sense to move away from that paradigm. An example of why I think thinking of comments in the context of nodes is problematic (taken from this comment):
/* 1 */ function /* 2 */ foo(/* 3 */) /* 4 */ { /* 5 */ } /* 6 */
Are comments, 2, 3, 4, and 5 leading comments or trailing comments? I would argue that 4 is a leading comment for the BlockStatement, but otherwise I don’t really think the rest fit into either category. In Espree, because it collected all comments as it parsed and would attach them as it was finishing up nodes, it would end up attaching a number of inner comments as trailing
comments. And since we didn’t have the token iterator methods we do now, it ended up allowing us to access comments inside “empty” nodes (such as the BlockStatement above), since those comments didn’t have a node right before or after. Given the weirdness that ensues (and now that we don’t have to be beholden to it!), I’d like to start moving towards thinking of comments in the context of tokens.
I’d like to propose landing https://github.com/eslint/eslint/pull/7516 and then deprecating sourceCode.getComments()
in favor of three other methods:
sourceCode.getCommentsBefore()
sourceCode.getCommentsAfter()
sourceCode.getCommentsInside()
It seems to be a pretty rare case where rules would need to access comments in both directions, so I think it makes sense to think of them separately. I’m envisioning that they would be purely token based (not attempting to “dedupe” based on whether they could be attached to a parent node as getComments()
currently does) with the following behavior:
// Collect comments before the node until it hits a non-comment token (the current behavior of
// getComments() minus the parent's range check)
sourceCode.getCommentsBefore(node) {
const comments = [];
let currentToken = this.getTokenBefore(node, { includeComments: true });
while (currentToken && astUtils.isCommentToken(currentToken)) {
comments.leading.unshift(currentToken);
currentToken = this.getTokenBefore(currentToken, { includeComments: true });
}
return comments;
}
// Collect comments after the node until it hits a non-comment token (the current behavior of
// getComments() minus the parent's range check)
sourceCode.getCommentsAfter(node) {
const comments = [];
let currentToken = this.getTokenAfter(node, { includeComments: true });
while (currentToken && astUtils.isCommentToken(currentToken)) {
comments.trailing.push(currentToken);
currentToken = this.getTokenAfter(currentToken, { includeComments: true });
}
return comments;
}
// Return all comment tokens inside the current Node (regardless of whether they are inside children nodes)
sourceCode.getCommentsInside(node) {
return this.getTokens(node, {
includeComments: true,
filter: astUtils.isCommentToken
});
}
Again, we would only deprecate getComments
right now - we would still leave it for backwards compatibility (as much as we have been able to approximate given the constraints of not being able to do it at parse time) and remove it in a future major version.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:6
- Comments:5 (5 by maintainers)
Top GitHub Comments
That’s fair! I’ll make a PR this weekend.
This was accepted in the 2017-04-13 TSC meeting.