33 */
44
55import { createRequire } from "node:module" ;
6- import { sourceText , initSourceText } from "./source_code.js" ;
6+ import { sourceText } from "./source_code.js" ;
77import { debugAssert , debugAssertIsNonNull } from "../utils/asserts.js" ;
88
99import type { Comment , Node , NodeOrToken } from "./types.ts" ;
@@ -1699,10 +1699,6 @@ export function getTokenByRangeStart(
16991699 return null ;
17001700}
17011701
1702- // Regex that tests for whitespace.
1703- // TODO: Is this too liberal? Should it be a more constrained set of whitespace characters?
1704- const WHITESPACE_REGEXP = / \s / ;
1705-
17061702/**
17071703 * Determine if two nodes or tokens have at least one whitespace character between them.
17081704 * Order does not matter.
@@ -1717,47 +1713,64 @@ const WHITESPACE_REGEXP = /\s/;
17171713 * Note: `checkInsideOfJSXText === false` in ESLint's implementation of `sourceCode.isSpaceBetween`. hmmmmmm
17181714 * https://github.com/eslint/eslint/blob/523c076866400670fb2192a3f55dbf7ad3469247/lib/languages/js/source-code/source-code.js#L182-L230
17191715 *
1720- * @param nodeOrToken1 - The first node or token to check between.
1721- * @param nodeOrToken2 - The second node or token to check between.
1716+ * @param first - The first node or token to check between.
1717+ * @param second - The second node or token to check between.
17221718 * @returns `true` if there is a whitespace character between
17231719 * any of the tokens found between the two given nodes or tokens.
17241720 */
1725- export function isSpaceBetween ( nodeOrToken1 : NodeOrToken , nodeOrToken2 : NodeOrToken ) : boolean {
1726- const range1 = nodeOrToken1 . range ,
1727- range2 = nodeOrToken2 . range ,
1728- start1 = range1 [ 0 ] ,
1729- start2 = range2 [ 0 ] ;
1730-
1731- // Find the gap between the two nodes/tokens.
1732- //
1733- // 1 node/token can completely enclose another, but they can't *partially* overlap.
1734- // ```
1735- // Possible:
1736- // |------------|
1737- // |------|
1738- //
1739- // Impossible:
1740- // |------------|
1741- // |------------|
1742- // ```
1743- // We use that invariant to reduce this to a single branch.
1744- let gapStart , gapEnd ;
1745- if ( start1 < start2 ) {
1746- gapStart = range1 [ 1 ] ; // end1
1747- gapEnd = start2 ;
1721+ export function isSpaceBetween ( first : NodeOrToken , second : NodeOrToken ) : boolean {
1722+ if ( tokens === null ) initTokens ( ) ;
1723+ if ( tokensWithComments === null ) initTokensWithComments ( ) ;
1724+ debugAssertIsNonNull ( tokensWithComments ) ;
1725+
1726+ const tokensWithCommentsLength = tokensWithComments . length ,
1727+ range1 = first . range ,
1728+ range2 = second . range ;
1729+
1730+ // The "between" range0
1731+ let rangeStart : number , rangeEnd : number ;
1732+
1733+ // Unlike other methods which require the user to pass the nodes in order of appearance,
1734+ // `isSpaceBetween()` is invariant over the sequence of the of the two nodes
1735+ if ( range1 [ 0 ] < range2 [ 0 ] ) {
1736+ rangeStart = range1 [ 1 ] ;
1737+ rangeEnd = range2 [ 0 ] ;
17481738 } else {
1749- gapStart = range2 [ 1 ] ; // end2 ;
1750- gapEnd = start1 ;
1739+ rangeStart = range2 [ 1 ] ;
1740+ rangeEnd = range1 [ 0 ] ;
17511741 }
17521742
1753- // If `gapStart >= gapEnd`, one node encloses the other, or the two are directly adjacent
1754- if ( gapStart >= gapEnd ) return false ;
1743+ // Binary search for the first token past `rangeStart`
1744+ // Unless `first` and `second` are adjacent or overlapping,
1745+ // the token will be the first token between the two nodes
1746+ let tokenBetweenIndex = tokensWithCommentsLength ;
1747+ for ( let lo = 0 ; lo < tokenBetweenIndex ; ) {
1748+ const mid = ( lo + tokenBetweenIndex ) >> 1 ;
1749+ if ( tokensWithComments [ mid ] . range [ 0 ] < rangeStart ) {
1750+ lo = mid + 1 ;
1751+ } else {
1752+ tokenBetweenIndex = mid ;
1753+ }
1754+ }
17551755
1756- // Check if there's any whitespace in the gap
1757- if ( sourceText === null ) initSourceText ( ) ;
1758- debugAssertIsNonNull ( sourceText ) ;
1756+ for (
1757+ let lastTokenEnd = rangeStart ;
1758+ tokenBetweenIndex < tokensWithCommentsLength ;
1759+ tokenBetweenIndex ++
1760+ ) {
1761+ const tokenRange = tokensWithComments [ tokenBetweenIndex ] . range ;
1762+ const tokenStart = tokenRange [ 0 ] ;
1763+ // The first token of the later node should undergo the check in the second branch
1764+ if ( tokenStart > rangeEnd ) {
1765+ break ;
1766+ } else if ( tokenStart !== lastTokenEnd ) {
1767+ return true ;
1768+ } else {
1769+ lastTokenEnd = tokenRange [ 1 ] ;
1770+ }
1771+ }
17591772
1760- return WHITESPACE_REGEXP . test ( sourceText . slice ( gapStart , gapEnd ) ) ;
1773+ return false ;
17611774}
17621775
17631776/**
0 commit comments