11import * as ts from 'typescript' ; // leave this as * as ts so people using util package don't need syntheticDefaultImports
2- import { getLocFor , getNodeContainer } from './node-utils' ;
2+ import { forEachComment } from 'tsutils' ;
3+ import { getLocFor } from './node-utils' ;
34import { TSESTree } from './ts-estree' ;
45
5- /**
6- * Converts a TypeScript comment to an Esprima comment.
7- * @param block True if it's a block comment, false if not.
8- * @param text The text of the comment.
9- * @param start The index at which the comment starts.
10- * @param end The index at which the comment ends.
11- * @param startLoc The location at which the comment starts.
12- * @param endLoc The location at which the comment ends.
13- * @returns The comment object.
14- * @internal
15- */
16- function convertTypeScriptCommentToEsprimaComment (
17- block : boolean ,
18- text : string ,
19- start : number ,
20- end : number ,
21- startLoc : TSESTree . LineAndColumnData ,
22- endLoc : TSESTree . LineAndColumnData ,
23- ) : TSESTree . Comment {
24- const comment : TSESTree . OptionalRangeAndLoc < TSESTree . Comment > = {
25- type : block ? 'Block' : 'Line' ,
26- value : text ,
27- } ;
28-
29- if ( typeof start === 'number' ) {
30- comment . range = [ start , end ] ;
31- }
32-
33- if ( typeof startLoc === 'object' ) {
34- comment . loc = {
35- start : startLoc ,
36- end : endLoc ,
37- } ;
38- }
39-
40- return comment as TSESTree . Comment ;
41- }
42-
43- /**
44- * Convert comment from TypeScript Triva Scanner.
45- * @param triviaScanner TS Scanner
46- * @param ast the AST object
47- * @param code TypeScript code
48- * @returns the converted Comment
49- * @private
50- */
51- function getCommentFromTriviaScanner (
52- triviaScanner : ts . Scanner ,
53- ast : ts . SourceFile ,
54- code : string ,
55- ) : TSESTree . Comment {
56- const kind = triviaScanner . getToken ( ) ;
57- const isBlock = kind === ts . SyntaxKind . MultiLineCommentTrivia ;
58- const range = {
59- pos : triviaScanner . getTokenPos ( ) ,
60- end : triviaScanner . getTextPos ( ) ,
61- kind : triviaScanner . getToken ( ) ,
62- } ;
63-
64- const comment = code . substring ( range . pos , range . end ) ;
65- const text = isBlock
66- ? comment . replace ( / ^ \/ \* / , '' ) . replace ( / \* \/ $ / , '' )
67- : comment . replace ( / ^ \/ \/ / , '' ) ;
68- const loc = getLocFor ( range . pos , range . end , ast ) ;
69-
70- return convertTypeScriptCommentToEsprimaComment (
71- isBlock ,
72- text ,
73- range . pos ,
74- range . end ,
75- loc . start ,
76- loc . end ,
77- ) ;
78- }
79-
806/**
817 * Convert all comments for the given AST.
828 * @param ast the AST object
@@ -90,93 +16,33 @@ export function convertComments(
9016) : TSESTree . Comment [ ] {
9117 const comments : TSESTree . Comment [ ] = [ ] ;
9218
93- /**
94- * Create a TypeScript Scanner, with skipTrivia set to false so that
95- * we can parse the comments
96- */
97- const triviaScanner = ts . createScanner (
98- ast . languageVersion ,
99- false ,
100- ast . languageVariant ,
101- code ,
19+ forEachComment (
20+ ast ,
21+ ( _ , comment ) => {
22+ const type =
23+ comment . kind == ts . SyntaxKind . SingleLineCommentTrivia
24+ ? 'Line'
25+ : 'Block' ;
26+ const range : TSESTree . Range = [ comment . pos , comment . end ] ;
27+ const loc = getLocFor ( range [ 0 ] , range [ 1 ] , ast ) ;
28+
29+ // both comments start with 2 characters - /* or //
30+ const textStart = range [ 0 ] + 2 ;
31+ const textEnd =
32+ comment . kind === ts . SyntaxKind . SingleLineCommentTrivia
33+ ? // single line comments end at the end
34+ range [ 1 ] - textStart
35+ : // multiline comments end 2 characters early
36+ range [ 1 ] - textStart - 2 ;
37+ comments . push ( {
38+ type,
39+ value : code . substr ( textStart , textEnd ) ,
40+ range,
41+ loc,
42+ } ) ;
43+ } ,
44+ ast ,
10245 ) ;
10346
104- let kind = triviaScanner . scan ( ) ;
105- while ( kind !== ts . SyntaxKind . EndOfFileToken ) {
106- const start = triviaScanner . getTokenPos ( ) ;
107- const end = triviaScanner . getTextPos ( ) ;
108-
109- let container : ts . Node | null = null ;
110- switch ( kind ) {
111- case ts . SyntaxKind . SingleLineCommentTrivia :
112- case ts . SyntaxKind . MultiLineCommentTrivia : {
113- const comment = getCommentFromTriviaScanner ( triviaScanner , ast , code ) ;
114-
115- comments . push ( comment ) ;
116- break ;
117- }
118- case ts . SyntaxKind . GreaterThanToken :
119- container = getNodeContainer ( ast , start , end ) ;
120- if (
121- ( container . parent &&
122- container . parent . parent &&
123- // Rescan after an opening element or fragment
124- ( container . parent . kind === ts . SyntaxKind . JsxOpeningElement &&
125- // Make sure this is the end of a tag like `<Component<number>>`
126- container . parent . end === end ) ) ||
127- container . parent . kind === ts . SyntaxKind . JsxOpeningFragment ||
128- // Rescan after a self-closing element if it's inside another JSX element
129- ( container . parent . kind === ts . SyntaxKind . JsxSelfClosingElement &&
130- ( container . parent . parent . kind === ts . SyntaxKind . JsxElement ||
131- container . parent . parent . kind === ts . SyntaxKind . JsxFragment ) ) ||
132- // Rescan after a closing element if it's inside another JSX element
133- ( ( container . parent . kind === ts . SyntaxKind . JsxClosingElement ||
134- container . parent . kind === ts . SyntaxKind . JsxClosingFragment ) &&
135- container . parent . parent . parent &&
136- ( container . parent . parent . parent . kind === ts . SyntaxKind . JsxElement ||
137- container . parent . parent . parent . kind ===
138- ts . SyntaxKind . JsxFragment ) )
139- ) {
140- kind = triviaScanner . reScanJsxToken ( ) ;
141- continue ;
142- }
143- break ;
144- case ts . SyntaxKind . CloseBraceToken :
145- container = getNodeContainer ( ast , start , end ) ;
146-
147- // Rescan after a JSX expression
148- if (
149- container . parent &&
150- container . parent . kind === ts . SyntaxKind . JsxExpression &&
151- container . parent . parent &&
152- container . parent . parent . kind === ts . SyntaxKind . JsxElement
153- ) {
154- kind = triviaScanner . reScanJsxToken ( ) ;
155- continue ;
156- }
157-
158- if (
159- container . kind === ts . SyntaxKind . TemplateMiddle ||
160- container . kind === ts . SyntaxKind . TemplateTail
161- ) {
162- kind = triviaScanner . reScanTemplateToken ( ) ;
163- continue ;
164- }
165- break ;
166- case ts . SyntaxKind . SlashToken :
167- case ts . SyntaxKind . SlashEqualsToken :
168- container = getNodeContainer ( ast , start , end ) ;
169-
170- if ( container . kind === ts . SyntaxKind . RegularExpressionLiteral ) {
171- kind = triviaScanner . reScanSlashToken ( ) ;
172- continue ;
173- }
174- break ;
175- default :
176- break ;
177- }
178- kind = triviaScanner . scan ( ) ;
179- }
180-
18147 return comments ;
18248}
0 commit comments