@@ -1105,27 +1105,115 @@ export function getTokensAfter(
11051105
11061106/**
11071107 * Get all of the tokens between two non-overlapping nodes.
1108- * @param nodeOrToken1 - Node before the desired token range.
1109- * @param nodeOrToken2 - Node after the desired token range.
1108+ * @param left - Node or token before the desired token range.
1109+ * @param right - Node or token after the desired token range.
11101110 * @param countOptions? - Options object. If this is a function then it's `options.filter`.
1111- * @returns Array of `Token`s between `nodeOrToken1 ` and `nodeOrToken2 `.
1111+ * @returns Array of `Token`s between `left ` and `right `.
11121112 */
11131113/**
11141114 * Get all of the tokens between two non-overlapping nodes.
1115- * @param nodeOrToken1 - Node before the desired token range.
1116- * @param nodeOrToken2 - Node after the desired token range.
1115+ * @param left - Node or token before the desired token range.
1116+ * @param right - Node or token after the desired token range.
11171117 * @param padding - Number of extra tokens on either side of center.
1118- * @returns Array of `Token`s between `nodeOrToken1 ` and `nodeOrToken2 `.
1118+ * @returns Array of `Token`s between `left ` and `right `.
11191119 */
1120- /* oxlint-disable no-unused-vars */
11211120export function getTokensBetween (
1122- nodeOrToken1 : NodeOrToken | Comment ,
1123- nodeOrToken2 : NodeOrToken | Comment ,
1121+ left : NodeOrToken | Comment ,
1122+ right : NodeOrToken | Comment ,
11241123 countOptions ?: CountOptions | number | FilterFn | null ,
11251124) : Token [ ] {
1126- throw new Error ( '`sourceCode.getTokensBetween` not implemented yet' ) ; // TODO
1125+ if ( tokens === null ) initTokens ( ) ;
1126+ debugAssertIsNonNull ( tokens ) ;
1127+ debugAssertIsNonNull ( comments ) ;
1128+
1129+ const count = typeof countOptions === 'object' && countOptions !== null ? countOptions . count : null ;
1130+
1131+ const padding = typeof countOptions === 'number' ? countOptions : 0 ;
1132+
1133+ const filter =
1134+ typeof countOptions === 'function'
1135+ ? countOptions
1136+ : typeof countOptions === 'object' && countOptions !== null
1137+ ? countOptions . filter
1138+ : null ;
1139+
1140+ const includeComments =
1141+ typeof countOptions === 'object' &&
1142+ countOptions !== null &&
1143+ 'includeComments' in countOptions &&
1144+ countOptions . includeComments ;
1145+
1146+ let nodeTokens : Token [ ] ;
1147+ if ( includeComments ) {
1148+ if ( tokensWithComments === null ) initTokensWithComments ( ) ;
1149+ debugAssertIsNonNull ( tokensWithComments ) ;
1150+ nodeTokens = tokensWithComments ;
1151+ } else {
1152+ nodeTokens = tokens ;
1153+ }
1154+
1155+ // This range is not invariant over node order.
1156+ // The first argument must be the left node.
1157+ // Same as ESLint's implementation.
1158+ const rangeStart = left . range [ 1 ] ,
1159+ rangeEnd = right . range [ 0 ] ,
1160+ tokensLength = nodeTokens . length ;
1161+
1162+ // Binary search for first token past the beginning of the `between` range
1163+ let sliceStart = tokensLength ;
1164+ for ( let lo = 0 ; lo < sliceStart ; ) {
1165+ const mid = ( lo + sliceStart ) >> 1 ;
1166+ if ( nodeTokens [ mid ] . range [ 0 ] < rangeStart ) {
1167+ lo = mid + 1 ;
1168+ } else {
1169+ sliceStart = mid ;
1170+ }
1171+ }
1172+
1173+ // Binary search for first token past the end of the `between` range
1174+ let sliceEnd = tokensLength ;
1175+ for ( let lo = sliceStart ; lo < sliceEnd ; ) {
1176+ const mid = ( lo + sliceEnd ) >> 1 ;
1177+ if ( nodeTokens [ mid ] . range [ 0 ] < rangeEnd ) {
1178+ lo = mid + 1 ;
1179+ } else {
1180+ sliceEnd = mid ;
1181+ }
1182+ }
1183+
1184+ // Apply padding
1185+ sliceStart = max ( 0 , sliceStart - padding ) ;
1186+ sliceEnd += padding ;
1187+
1188+ let tokensBetween : Token [ ] ;
1189+ if ( typeof filter !== 'function' ) {
1190+ if ( typeof count !== 'number' ) {
1191+ tokensBetween = nodeTokens . slice ( sliceStart , sliceEnd ) ;
1192+ } else {
1193+ tokensBetween = nodeTokens . slice ( sliceStart , min ( sliceStart + count , sliceEnd ) ) ;
1194+ }
1195+ } else {
1196+ if ( typeof count !== 'number' ) {
1197+ tokensBetween = [ ] ;
1198+ for ( let i = sliceStart ; i < sliceEnd ; i ++ ) {
1199+ const token = nodeTokens [ i ] ;
1200+ if ( filter ( token ) ) {
1201+ tokensBetween . push ( token ) ;
1202+ }
1203+ }
1204+ } else {
1205+ tokensBetween = [ ] ;
1206+ for ( let i = sliceStart ; i < sliceEnd && tokensBetween . length < count ; i ++ ) {
1207+ const token = nodeTokens [ i ] ;
1208+ if ( filter ( token ) ) {
1209+ tokensBetween . push ( token ) ;
1210+ }
1211+ }
1212+ }
1213+ }
1214+
1215+ return tokensBetween ;
11271216}
1128- /* oxlint-enable no-unused-vars */
11291217
11301218/**
11311219 * Get the first token between two non-overlapping nodes.
0 commit comments