@@ -7,6 +7,13 @@ import { ToolProgressStatus } from "@roo-code/types"
77import { addLineNumbers , everyLineHasLineNumbers , stripLineNumbers } from "../../../integrations/misc/extract-text"
88import { ToolUse , DiffStrategy , DiffResult } from "../../../shared/tools"
99import { normalizeString } from "../../../utils/text-normalization"
10+ import { SuperfluousDuplicatedLineEngine } from "./engines/superfluous-duplicated-line.engine"
11+
12+ export interface SearchReplaceContext {
13+ startLine : number
14+ searchContent : string
15+ replaceContent : string
16+ }
1017
1118const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
1219
@@ -406,6 +413,19 @@ Only use a single line of '=======' between search and replacement content, beca
406413 let { searchContent, replaceContent } = replacement
407414 let startLine = replacement . startLine + ( replacement . startLine === 0 ? 0 : delta )
408415
416+ // --- Start: Replacement Engine Processing ---
417+ let context = SuperfluousDuplicatedLineEngine . process ( originalContent , {
418+ startLine,
419+ searchContent,
420+ replaceContent,
421+ } )
422+
423+ // Update variables from engine processing
424+ startLine = context . startLine
425+ searchContent = context . searchContent
426+ replaceContent = context . replaceContent
427+ // --- End: Replacement Engine Processing ---
428+
409429 // First unescape any escaped markers in the content
410430 searchContent = this . unescapeMarkers ( searchContent )
411431 replaceContent = this . unescapeMarkers ( replaceContent )
@@ -591,33 +611,6 @@ Only use a single line of '=======' between search and replacement content, beca
591611 // Initialize effectiveSearchLinesCount (determines how many lines from original are considered "replaced")
592612 let effectiveSearchLinesCount = searchLines . length // Default
593613
594- // Heuristic to adjust effectiveSearchLinesCount for superfluous duplicated line pattern
595- if ( searchLines . length > 0 && replaceLines . length > searchLines . length ) {
596- const searchBlockContent = searchLines . join ( "\n" )
597- // Ensure replaceLines has enough elements before slicing
598- const firstPartOfReplaceBlock = replaceLines . slice ( 0 , searchLines . length ) . join ( "\n" )
599-
600- // Check if the search content is highly similar to the beginning of the replace content
601- if ( getSimilarity ( searchBlockContent , firstPartOfReplaceBlock ) > 0.95 ) {
602- // Ensure there's a line in replaceLines immediately after the part that matches searchLines
603- if ( searchLines . length < replaceLines . length ) {
604- const lineInReplaceAfterPrefix = replaceLines [ searchLines . length ]
605-
606- // Ensure there's a line in the original content (resultLines) immediately after the matched search block
607- if ( matchIndex + searchLines . length < resultLines . length ) {
608- const lineInOriginalAfterMatchedSearch = resultLines [ matchIndex + searchLines . length ]
609-
610- // If the line in the replace block (after the prefix) is identical (ignoring leading/trailing whitespace)
611- // to the line in the original content (after the search match),
612- // it's likely a duplicated line scenario.
613- if ( lineInReplaceAfterPrefix . trim ( ) === lineInOriginalAfterMatchedSearch . trim ( ) ) {
614- effectiveSearchLinesCount = searchLines . length + 1 // Consume the duplicated line from the original
615- }
616- }
617- }
618- }
619- }
620-
621614 // Construct the final content
622615 const beforeMatch = resultLines . slice ( 0 , matchIndex )
623616 // Use effectiveSearchLinesCount here to determine the slice point
0 commit comments