Skip to content

Commit 7f47e48

Browse files
committed
Add comment nodes rfc.
1 parent e6b8dad commit 7f47e48

File tree

2 files changed

+196
-1
lines changed

2 files changed

+196
-1
lines changed

rfcs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ This is a very loose RFC process. The implementation may slightly differ.
1010

1111
## In Progress
1212

13-
* None
13+
* [RFC-0002](RFC-0002 - Comment Nodes For All Comments.md) - Comment nodes for all comments.
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# RFC-0002 - Comment Nodes For All Comments
2+
3+
## Prerequisites
4+
5+
* Understand comment ownership: https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview#trivia
6+
* Understand the difference between `getChildren()` and `forEachChild` in the compiler API.
7+
8+
## Issues
9+
10+
* [#737](https://github.com/dsherret/ts-morph/issues/737) - Parse out all comments as children.
11+
* [#721](https://github.com/dsherret/ts-morph/issues/721) - `file.getDescendantsOfKind(SyntaxKind.SingleLineCommentTrivia)` does not return all comments
12+
13+
## Problem
14+
15+
It is difficult to deal with comments in ts-morph. RFC-0001 made it somewhat easier by introducing the concept of "comment nodes", which had "comment statement" and "comment member" implementations, but it didn't go far enough. There are still many comments that need to be parsed out each time from the compiler.
16+
17+
## `Node#getChildrenWithComments()`
18+
19+
This RFC proposes the following:
20+
21+
1. Comment statements & members will be changed to "comment list statements" and "comment list members".
22+
2. `Node#getChildren()` will return these comment lists instead of just a single comment node (which was the first comment on the line).
23+
3. Add new `Node#getChildrenWithComments()` method that works the same as `Node#getChildren()`, but additionally parses out and returns comments as objects that implement the `ts.Node` interface.
24+
25+
### Example
26+
27+
Given the following code:
28+
29+
```ts
30+
// 1
31+
/*2*/ // 3
32+
/*4*/ test/*5*/; //6
33+
/*7*/ //8
34+
```
35+
36+
The current tree representation using `Node#getChildren()` in ts-morph is the following as per RFC-0001:
37+
38+
```
39+
SourceFile
40+
SyntaxList
41+
CommentStatement (// 1)
42+
CommentStatement (/*2*/)
43+
ExpressionStatement
44+
Identifier
45+
SemiColonToken
46+
CommentStatement (/*7*/)
47+
EndOfFileToken
48+
```
49+
50+
The new implementation of `Node#getChildren()` will return the following:
51+
52+
```
53+
SourceFile
54+
SyntaxList
55+
CommentListStatement
56+
SingleLineCommentTrivia
57+
CommentListStatement
58+
MultiLineCommentTrivia
59+
SingleLineCommentTrivia
60+
ExpressionStatement
61+
Identifier
62+
SemiColonToken
63+
CommentListStatement
64+
MultiLineCommentTrivia
65+
SingleLineCommentTrivia
66+
EndOfFileToken
67+
```
68+
69+
Then `#getChildrenWithComments()` would return the following:
70+
71+
```
72+
SourceFile
73+
SyntaxList
74+
CommentListStatement
75+
SingleLineCommentTrivia
76+
CommentListStatement
77+
MultiLineCommentTrivia
78+
SingleLineCommentTrivia
79+
MultiLineCommentTrivia
80+
ExpressionStatement
81+
Identifier
82+
MultiLineCommentTrivia
83+
SemiColonToken
84+
SingleLineCommentTrivia
85+
CommentListStatement
86+
MultiLineCommentTrivia
87+
SingleLineCommentTrivia
88+
EndOfFileToken
89+
```
90+
91+
## Comment Node
92+
93+
Comment nodes are any single line or multi-line comment in the file. They will work the same as the comment nodes described in RFC-0001. The only difference now is that any comment can be represented by a comment node and there is now an introduction of "comment lists".
94+
95+
## Comment Lists
96+
97+
Comment lists are a collection of comments located in the statements of a node or members of nodes like interfaces/classes/etc. that are on one line without any other tokens on that line.
98+
99+
They show up in methods like `#getStatementsWithComments()`, `#getChildren()`, and the new `#getChildrenWithComments()`. For example, the following is a comment list:
100+
101+
```ts
102+
/*1*/ /*2*/ //3
103+
```
104+
105+
Tree representation:
106+
107+
```
108+
CommentListStatement
109+
MultiLineCommentTrivia (/*1*/)
110+
MultiLineCommentTrivia (/*2*/)
111+
SingleLineCommentTrivia (//3)
112+
```
113+
114+
As described in RFC-0001 about comment statements & members, this is done to allow inserting before and after certain comments.
115+
116+
### JS Docs
117+
118+
JS docs are special and are not comment lists. They are included as children of the declaration they describe in the compiler API.
119+
120+
Additionally, any comments that appear after a JS doc and before the declaration start are not comment lists.
121+
122+
For example the following code:
123+
124+
```ts
125+
// 1
126+
127+
/** My function. */
128+
//2
129+
function myFunction() {}
130+
```
131+
132+
Has the following tree when using `#getChildrenWithComments()`:
133+
134+
```
135+
SourceFile
136+
SyntaxList
137+
CommentListStatement
138+
SingleLineCommentTrivia
139+
FunctionDeclaration
140+
JSDocComment
141+
SingleLineCommentTrivia
142+
FunctionKeyword
143+
Identifier
144+
OpenParenToken
145+
SyntaxList
146+
CloseParenToken
147+
Block
148+
OpenBraceToken
149+
SyntaxList
150+
CloseBraceToken
151+
EndOfFileToken
152+
```
153+
154+
### Types
155+
156+
```ts
157+
export enum CommentListKind {
158+
Statement,
159+
ClassElement,
160+
TypeElement,
161+
ObjectLiteralElement,
162+
EnumMember
163+
}
164+
```
165+
166+
Base type:
167+
168+
```ts
169+
interface CompilerCommentList implements ts.Node {
170+
commentListKind: CommentListKind;
171+
comments: CompilerCommentNode[];
172+
}
173+
```
174+
175+
### `ts.SyntaxKind` choise
176+
177+
The major downside here is that unlike comment nodes which use either `ts.SyntaxKind.MultiLineCommentTrivia` or `ts.SyntaxKind.SingleLineCommentTrivia`, there is no existing `ts.SyntaxKind` that works well for comment lists. The only available option seems to be to use a custom number or `ts.SyntaxKind.Unknown` (`0`), which I think is what I'm going to go with because that is in the set of `ts.SyntaxKind`.
178+
179+
## Comments Inside Syntax Lists With Statements or Members
180+
181+
For example:
182+
183+
```ts
184+
{
185+
//1
186+
a;
187+
//2
188+
}
189+
```
190+
191+
The syntax list of the block ends at the semi-colon of `a;`, but when calling `#getChildrenWithComments()` on the syntax list, it should return all the comments up to the close brace token.
192+
193+
## Comment children ownership
194+
195+
Child comments are any comment that is found within `Node#.getStart(true)` (`true` meaning the start pos including js docs) and `Node#end` where no descendant node is true for that condition. The only exception to this is syntax lists with statements or members as described above.

0 commit comments

Comments
 (0)