11import { SearchReplaceContext } from "../multi-search-replace"
22
33export class SuperfluousDuplicatedLineEngine {
4- public static process ( originalContent : string , context : SearchReplaceContext ) : SearchReplaceContext {
4+ /**
5+ * Processes a search/replace context to detect superfluous duplicated lines.
6+ *
7+ * @param originalContent The complete original content being modified
8+ * @param context The search/replace context containing startLine, searchContent, and replaceContent
9+ * @returns The number of additional lines from the original content that should be consumed
10+ * to prevent duplication. Returns 0 if no additional lines should be consumed.
11+ */
12+ public static process ( originalContent : string , context : SearchReplaceContext ) : number {
513 const { startLine, searchContent, replaceContent } = context
614
715 // Early detection of superfluous duplicated line pattern
@@ -18,29 +26,38 @@ export class SuperfluousDuplicatedLineEngine {
1826 const isFirstPartSimilar = firstPartOfReplace === searchContent
1927
2028 if ( isFirstPartSimilar && replaceLines . length > searchLines . length ) {
21- // Get the line that comes after the search block in replace content
22- const lineAfterSearchInReplace = replaceLines [ searchLines . length ]
23-
24- // Get the line that comes after the search block in original content
25- const lineIndexInOriginal = startLine - 1 + searchLines . length
26- if ( lineIndexInOriginal < originalLines . length ) {
27- const lineAfterSearchInOriginal = originalLines [ lineIndexInOriginal ]
28-
29- // If they match, it's likely a superfluous duplicated line scenario
30- // We can modify the search content to include the extra line
31- if ( lineAfterSearchInReplace . trim ( ) === lineAfterSearchInOriginal . trim ( ) ) {
32- const modifiedSearchContent = searchContent + "\n" + lineAfterSearchInOriginal
33- return {
34- startLine,
35- searchContent : modifiedSearchContent ,
36- replaceContent,
37- }
29+ // Check for any number of consecutive matching lines after the search block
30+ let matchingLinesCount = 0
31+ const searchEndIndex = startLine - 1 + searchLines . length
32+ const maxPossibleMatches = Math . min (
33+ replaceLines . length - searchLines . length , // Available lines in replace content
34+ originalLines . length - searchEndIndex , // Available lines in original content after search
35+ )
36+
37+ for ( let i = 0 ; i < maxPossibleMatches ; i ++ ) {
38+ const replaceLineIndex = searchLines . length + i
39+ const originalLineIndex = searchEndIndex + i
40+
41+ const lineInReplace = replaceLines [ replaceLineIndex ]
42+ const lineInOriginal = originalLines [ originalLineIndex ]
43+
44+ // Check if lines match (trimmed comparison to handle whitespace differences)
45+ if ( lineInReplace && lineInOriginal && lineInReplace . trim ( ) === lineInOriginal . trim ( ) ) {
46+ matchingLinesCount ++
47+ } else {
48+ // Stop at the first non-matching line
49+ break
3850 }
3951 }
52+
53+ // If we found any matching lines, return the count
54+ if ( matchingLinesCount > 0 ) {
55+ return matchingLinesCount
56+ }
4057 }
4158 }
4259
43- // No modification needed, return as-is
44- return context
60+ // No additional lines to consume
61+ return 0
4562 }
4663}
0 commit comments