@@ -6,6 +6,13 @@ import { DATA_POINTER_POS_32, SOURCE_LEN_OFFSET } from '../generated/constants.j
66import { deserializeProgramOnly , resetBuffer } from '../../dist/generated/deserialize.js' ;
77
88import visitorKeys from '../generated/keys.js' ;
9+ import {
10+ commentsExistBetween ,
11+ getAllComments ,
12+ getCommentsAfter ,
13+ getCommentsBefore ,
14+ getCommentsInside ,
15+ } from './comments.js' ;
916import {
1017 getLineColumnFromOffset ,
1118 getNodeLoc ,
@@ -21,8 +28,6 @@ import type { BufferWithArrays, Comment, Node, NodeOrToken, Ranged, Token } from
2128
2229const { max } = Math ;
2330
24- const WHITESPACE_ONLY_REGEXP = / ^ \s * $ / ;
25-
2631// Text decoder, for decoding source text from buffer
2732const textDecoder = new TextDecoder ( 'utf-8' , { ignoreBOM : true } ) ;
2833
@@ -157,161 +162,11 @@ export const SOURCE_CODE = Object.freeze({
157162 return sourceText . slice ( start , end ) ;
158163 } ,
159164
160- /**
161- * Retrieve an array containing all comments in the source code.
162- * @returns Array of `Comment`s in occurrence order.
163- */
164- getAllComments ( ) : Comment [ ] {
165- if ( ast === null ) initAst ( ) ;
166- // `comments` property is a getter. Comments are deserialized lazily.
167- return ast . comments ;
168- } ,
169-
170- /**
171- * Get all comment tokens directly before the given node or token.
172- * @param nodeOrToken - The AST node or token to check for adjacent comment tokens.
173- * @returns Array of `Comment`s in occurrence order.
174- */
175- getCommentsBefore ( nodeOrToken : NodeOrToken ) : Comment [ ] {
176- if ( ast === null ) initAst ( ) ;
177-
178- const { comments } = ast ,
179- commentsLength = comments . length ;
180-
181- let targetStart = nodeOrToken . range [ 0 ] ; // start
182-
183- let sliceStart = commentsLength ;
184- let sliceEnd = 0 ;
185-
186- // Reverse iteration isn't ideal, but this entire implementation may need to be rewritten
187- // with token-based APIs to match eslint.
188- for ( let i = commentsLength - 1 ; i >= 0 ; i -- ) {
189- const comment = comments [ i ] ;
190- const commentEnd = comment . end ;
191-
192- if ( commentEnd < targetStart ) {
193- const gap = sourceText . slice ( commentEnd , targetStart ) ;
194- if ( WHITESPACE_ONLY_REGEXP . test ( gap ) ) {
195- // Nothing except whitespace between end of comment and start of `nodeOrToken`
196- sliceStart = sliceEnd = i + 1 ;
197- targetStart = comment . start ;
198- }
199- break ;
200- }
201- }
202-
203- for ( let i = sliceEnd - 1 ; i >= 0 ; i -- ) {
204- const comment = comments [ i ] ;
205- const gap = sourceText . slice ( comment . end , targetStart ) ;
206- if ( WHITESPACE_ONLY_REGEXP . test ( gap ) ) {
207- // Nothing except whitespace between end of comment and start of `nodeOrToken`
208- sliceStart = i ;
209- targetStart = comment . start ;
210- } else {
211- break ;
212- }
213- }
214-
215- return comments . slice ( sliceStart , sliceEnd ) ;
216- } ,
217-
218- /**
219- * Get all comment tokens directly after the given node or token.
220- * @param nodeOrToken - The AST node or token to check for adjacent comment tokens.
221- * @returns Array of `Comment`s in occurrence order.
222- */
223- getCommentsAfter ( nodeOrToken : NodeOrToken ) : Comment [ ] {
224- if ( ast === null ) initAst ( ) ;
225-
226- const { comments } = ast ,
227- commentsLength = comments . length ;
228-
229- let targetEnd = nodeOrToken . range [ 1 ] ; // end
230-
231- const commentsAfter : Comment [ ] = [ ] ;
232- for ( let i = 0 ; i < commentsLength ; i ++ ) {
233- const comment = comments [ i ] ,
234- commentStart = comment . start ;
235-
236- if ( commentStart < targetEnd ) {
237- continue ;
238- }
239- const gap = sourceText . slice ( targetEnd , commentStart ) ;
240- if ( WHITESPACE_ONLY_REGEXP . test ( gap ) ) {
241- // Nothing except whitespace between end of `nodeOrToken` and start of comment
242- commentsAfter . push ( comment ) ;
243- targetEnd = comment . end ;
244- } else {
245- break ;
246- }
247- }
248-
249- return commentsAfter ;
250- } ,
251-
252- /**
253- * Get all comment tokens inside the given node.
254- * @param node - The AST node to get the comments for.
255- * @returns Array of `Comment`s in occurrence order.
256- */
257- getCommentsInside ( node : Node ) : Comment [ ] {
258- if ( ast === null ) initAst ( ) ;
259-
260- const { comments } = ast ,
261- commentsLength = comments . length ;
262-
263- let sliceStart = commentsLength ;
264- let sliceEnd : number | undefined = undefined ;
265-
266- const { range } = node ,
267- rangeStart = range [ 0 ] ,
268- rangeEnd = range [ 1 ] ;
269-
270- // Linear search for first comment within `node`'s range.
271- // TODO: Use binary search.
272- for ( let i = 0 ; i < commentsLength ; i ++ ) {
273- const comment = comments [ i ] ;
274- if ( comment . start >= rangeStart ) {
275- sliceStart = i ;
276- break ;
277- }
278- }
279-
280- // Continued linear search for first comment outside `node`'s range.
281- // Its index is used as `sliceEnd`, which is exclusive of the slice.
282- for ( let i = sliceStart ; i < commentsLength ; i ++ ) {
283- const comment = comments [ i ] ;
284- if ( comment . start > rangeEnd ) {
285- sliceEnd = i ;
286- break ;
287- }
288- }
289-
290- return comments . slice ( sliceStart , sliceEnd ) ;
291- } ,
292-
293- /**
294- * Check whether any comments exist or not between the given 2 nodes.
295- * @param nodeOrToken1 - The node to check.
296- * @param nodeOrToken2 - The node to check.
297- * @returns `true` if one or more comments exist.
298- */
299- commentsExistBetween ( nodeOrToken1 : NodeOrToken , nodeOrToken2 : NodeOrToken ) : boolean {
300- if ( ast === null ) initAst ( ) ;
301-
302- // Find the first comment after `nodeOrToken1` ends.
303- // Check if it ends before `nodeOrToken2` starts.
304- const { comments } = ast ,
305- commentsLength = comments . length ;
306- const betweenRangeStart = nodeOrToken1 . range [ 1 ] ; // end
307- for ( let i = 0 ; i < commentsLength ; i ++ ) {
308- const comment = comments [ i ] ;
309- if ( comment . start >= betweenRangeStart ) {
310- return comment . end <= nodeOrToken2 . range [ 0 ] ; // start
311- }
312- }
313- return false ;
314- } ,
165+ getAllComments,
166+ getCommentsBefore,
167+ getCommentsAfter,
168+ getCommentsInside,
169+ commentsExistBetween,
315170
316171 /**
317172 * Determine if two nodes or tokens have at least one whitespace character between them.
0 commit comments