@@ -287,36 +287,6 @@ function findAllMatches(
287287 return positions ;
288288}
289289
290- /** Get the longest line from an array (most likely to be unique) */
291- function getLongestLine ( lines : string [ ] ) : string | null {
292- if ( lines . length === 0 ) {
293- return null ;
294- }
295-
296- let longest = lines [ 0 ] ;
297- for ( const line of lines ) {
298- if ( line . trim ( ) . length > longest . trim ( ) . length ) {
299- longest = line ;
300- }
301- }
302- return longest . trim ( ) . length > 0 ? longest : null ;
303- }
304-
305- /** Find line position in source */
306- function findLinePosition (
307- sourceLines : string [ ] ,
308- line : string ,
309- startFrom : number = 0
310- ) : number [ ] {
311- const positions : number [ ] = [ ] ;
312- const trimmedLine = line . trim ( ) ;
313- for ( let i = startFrom ; i < sourceLines . length ; i ++ ) {
314- if ( sourceLines [ i ] . trim ( ) === trimmedLine ) {
315- positions . push ( i ) ;
316- }
317- }
318- return positions ;
319- }
320290
321291/**
322292 * Find block position using three-layer fallback strategy
@@ -576,44 +546,28 @@ export function applyDiff(
576546 } else if ( allPositions . length > 1 ) {
577547 // Multiple matches - try to disambiguate using middle context
578548 if ( firstMiddleContext . length > 0 ) {
579- const longestMiddleLine = getLongestLine ( firstMiddleContext ) ;
549+ // Sort candidates to prefer those after lastBlockEnd
550+ const sortedCandidates = [ ...allPositions ] . sort ( ( a , b ) => {
551+ const aAfter =
552+ a + effectiveContext . length >= lastBlockEnd ? 0 : 1 ;
553+ const bAfter =
554+ b + effectiveContext . length >= lastBlockEnd ? 0 : 1 ;
555+ return aAfter - bAfter || a - b ;
556+ } ) ;
557+
558+ for ( const candidatePos of sortedCandidates ) {
559+ const changePos = candidatePos + effectiveContext . length ;
560+ const searchAfter = changePos + removals . length ;
580561
581- if ( longestMiddleLine ) {
582- // Find positions of the longest middle line
583- const middleLinePositions = findLinePosition (
562+ // Check if middle context matches after this candidate
563+ const middlePositions = findAllMatches (
584564 sourceLines ,
585- longestMiddleLine ,
586- 0
565+ firstMiddleContext ,
566+ searchAfter
587567 ) ;
588-
589- // For each candidate position, check if middle line appears after it
590- // Sort candidates to prefer those after lastBlockEnd
591- const sortedCandidates = [ ...allPositions ] . sort ( ( a , b ) => {
592- const aAfter =
593- a + effectiveContext . length >= lastBlockEnd ? 0 : 1 ;
594- const bAfter =
595- b + effectiveContext . length >= lastBlockEnd ? 0 : 1 ;
596- return aAfter - bAfter || a - b ;
597- } ) ;
598-
599- for ( const candidatePos of sortedCandidates ) {
600- const changePos = candidatePos + effectiveContext . length ;
601- const searchAfter = changePos + removals . length ;
602-
603- // Check if any middle line position is reasonably close after this candidate
604- for ( const middlePos of middleLinePositions ) {
605- if (
606- middlePos >= searchAfter &&
607- middlePos < searchAfter + 100
608- ) {
609- // Found: this candidate has the middle context after it
610- position = changePos ;
611- break ;
612- }
613- }
614- if ( position !== - 1 ) {
615- break ;
616- }
568+ if ( middlePositions . length > 0 && middlePositions [ 0 ] < searchAfter + 100 ) {
569+ position = changePos ;
570+ break ;
617571 }
618572 }
619573 }
@@ -641,6 +595,20 @@ export function applyDiff(
641595 position = findBlockPosition ( sourceLines , block , lastBlockEnd ) ;
642596 }
643597
598+ // Fallback: use firstMiddleContext to reverse-locate position
599+ // When context is wrong but middle context exists, find middle context position
600+ // and calculate insertion point by going back removals.length lines
601+ if ( position === - 1 && firstMiddleContext . length > 0 ) {
602+ const middlePositions = findAllMatches (
603+ sourceLines ,
604+ firstMiddleContext ,
605+ lastBlockEnd
606+ ) ;
607+ if ( middlePositions . length >= 1 ) {
608+ position = middlePositions [ 0 ] - removals . length ;
609+ }
610+ }
611+
644612 if ( position === - 1 ) {
645613 const context = block . contextBefore . slice ( 0 , 2 ) . join ( '\n' ) ;
646614 const removal = block . removals . slice ( 0 , 2 ) . join ( '\n' ) ;
0 commit comments