@@ -260,40 +260,61 @@ export function findFlagNotations(code: string, customTags: string[], tsOptionDe
260260}
261261
262262export function findCutNotations ( code : string , meta : Pick < TwoslashReturnMeta , 'removals' > ) {
263- const removals : Range [ ] = [ ]
263+ let removals : Range [ ] = [ ]
264+ const lines = code . split ( '\n' )
265+ const cutStarts : number [ ] = [ ]
266+ // start character after \n
267+ let idx = 0
268+ let lineIndex = 0
269+
270+ for ( const line of lines ) {
271+ const comment = line . trim ( )
272+
273+ if ( comment . match ( reCutBefore ) ) {
274+ removals = [ [ 0 , idx + line . length + 1 ] ]
275+ }
276+ else if ( comment . match ( reCutAfter ) ) {
277+ removals . push ( [ idx , code . length ] )
278+ break
279+ }
280+ else if ( comment . match ( reCutStart ) ) {
281+ cutStarts . push ( idx )
282+ }
283+ else if ( comment . match ( reCutEnd ) ) {
284+ const startIdx = cutStarts . pop ( )
285+
286+ if ( startIdx === undefined ) {
287+ const startLine = lines . findIndex ( ( line , i ) => i > lineIndex && line . trim ( ) . match ( reCutStart ) )
288+
289+ if ( startLine === - 1 ) {
290+ throw new TwoslashError (
291+ `Mismatched cut markers` ,
292+ `You have an unclosed the cut-end at line ${ lineIndex + 1 } ` ,
293+ `Make sure you have a matching pair for each.` ,
294+ )
295+ }
264296
265- const cutBefore = [ ...code . matchAll ( reCutBefore ) ]
266- const cutAfter = [ ...code . matchAll ( reCutAfter ) ]
267- const cutStart = [ ...code . matchAll ( reCutStart ) ]
268- const cutEnd = [ ...code . matchAll ( reCutEnd ) ]
297+ throw new TwoslashError (
298+ `Mismatched cut markers` ,
299+ `You have a cut-start at line ${ startLine + 1 } which is after the cut-end at line ${ lineIndex + 1 } ` ,
300+ `Make sure you have a matching pair for each.` ,
301+ )
302+ }
269303
270- if ( cutBefore . length ) {
271- const last = cutBefore [ cutBefore . length - 1 ]
272- removals . push ( [ 0 , last . index ! + last [ 0 ] . length ] )
273- }
274- if ( cutAfter . length ) {
275- const first = cutAfter [ 0 ]
276- removals . push ( [ first . index ! , code . length ] )
304+ removals . push ( [ startIdx , idx + line . length + 1 ] )
305+ }
306+
307+ lineIndex ++
308+ idx += line . length + 1
277309 }
278- if ( cutStart . length !== cutEnd . length ) {
310+
311+ if ( cutStarts . length > 0 ) {
279312 throw new TwoslashError (
280313 `Mismatched cut markers` ,
281- `You have ${ cutStart . length } cut-starts and ${ cutEnd . length } cut-ends ` ,
314+ `You have unclosed cut-starts at lines ${ cutStarts . join ( ', ' ) } ` ,
282315 `Make sure you have a matching pair for each.` ,
283316 )
284317 }
285- for ( let i = 0 ; i < cutStart . length ; i ++ ) {
286- const start = cutStart [ i ]
287- const end = cutEnd [ i ]
288- if ( start . index ! > end . index ! ) {
289- throw new TwoslashError (
290- `Mismatched cut markers` ,
291- `You have a cut-start at ${ start . index } which is after the cut-end at ${ end . index } ` ,
292- `Make sure you have a matching pair for each.` ,
293- )
294- }
295- removals . push ( [ start . index ! , end . index ! + end [ 0 ] . length ] )
296- }
297318
298319 if ( meta )
299320 meta . removals . push ( ...removals )
0 commit comments