Fix indentation bug with diff replacing a single search line

This commit is contained in:
Matt Rubens
2024-12-11 02:49:22 -05:00
parent 08a3d65daf
commit 77d7fc0a44
5 changed files with 54 additions and 60 deletions

View File

@@ -1,5 +1,9 @@
# Roo Cline Changelog # Roo Cline Changelog
## [2.2.1]
- Fix another diff editing indentation bug
## [2.2.0] ## [2.2.0]
- Incorporate MCP changes from Cline 2.2.0 - Incorporate MCP changes from Cline 2.2.0

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "roo-cline", "name": "roo-cline",
"version": "2.2.0", "version": "2.2.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "roo-cline", "name": "roo-cline",
"version": "2.2.0", "version": "2.2.1",
"dependencies": { "dependencies": {
"@anthropic-ai/bedrock-sdk": "^0.10.2", "@anthropic-ai/bedrock-sdk": "^0.10.2",
"@anthropic-ai/sdk": "^0.26.0", "@anthropic-ai/sdk": "^0.26.0",

View File

@@ -3,7 +3,7 @@
"displayName": "Roo Cline", "displayName": "Roo Cline",
"description": "A fork of Cline, an autonomous coding agent, with some added experimental configuration and automation features.", "description": "A fork of Cline, an autonomous coding agent, with some added experimental configuration and automation features.",
"publisher": "RooVeterinaryInc", "publisher": "RooVeterinaryInc",
"version": "2.2.0", "version": "2.2.1",
"icon": "assets/icons/rocket.png", "icon": "assets/icons/rocket.png",
"galleryBanner": { "galleryBanner": {
"color": "#617A91", "color": "#617A91",

View File

@@ -31,31 +31,6 @@ function hello() {
`) `)
}) })
it('should handle extra whitespace in search/replace blocks', () => {
const originalContent = `function test() {
return true;
}
`
const diffContent = `test.ts
<<<<<<< SEARCH
function test() {
return true;
}
=======
function test() {
return false;
}
>>>>>>> REPLACE`
const result = strategy.applyDiff(originalContent, diffContent)
expect(result).toBe(`function test() {
return false;
}
`)
})
it('should match content with different surrounding whitespace', () => { it('should match content with different surrounding whitespace', () => {
const originalContent = ` const originalContent = `
function example() { function example() {
@@ -286,6 +261,27 @@ Invalid diff format`
expect(result).toBe(" modified\n still indented\n end\n") expect(result).toBe(" modified\n still indented\n end\n")
}) })
it('should preserve indentation when adding new lines after existing content', () => {
const originalContent = ` onScroll={() => updateHighlights()}`
const diffContent = `test.ts
<<<<<<< SEARCH
onScroll={() => updateHighlights()}
=======
onScroll={() => updateHighlights()}
onDragOver={(e) => {
e.preventDefault()
e.stopPropagation()
}}
>>>>>>> REPLACE`
const result = strategy.applyDiff(originalContent, diffContent)
expect(result).toBe(` onScroll={() => updateHighlights()}
onDragOver={(e) => {
e.preventDefault()
e.stopPropagation()
}}`)
})
it('should handle complex refactoring with multiple functions', () => { it('should handle complex refactoring with multiple functions', () => {
const originalContent = `export async function extractTextFromFile(filePath: string): Promise<string> { const originalContent = `export async function extractTextFromFile(filePath: string): Promise<string> {
try { try {
@@ -519,3 +515,4 @@ export function addLineNumbers(content: string, startLine: number = 1): string {
}) })
}) })
}) })

View File

@@ -74,8 +74,8 @@ Your search/replace content here
const lineEnding = originalContent.includes('\r\n') ? '\r\n' : '\n'; const lineEnding = originalContent.includes('\r\n') ? '\r\n' : '\n';
// Split content into lines, handling both \n and \r\n // Split content into lines, handling both \n and \r\n
const searchLines = searchContent.trim().split(/\r?\n/); const searchLines = searchContent.split(/\r?\n/);
const replaceLines = replaceContent.trim().split(/\r?\n/); const replaceLines = replaceContent.split(/\r?\n/);
const originalLines = originalContent.split(/\r?\n/); const originalLines = originalContent.split(/\r?\n/);
// Find the search content in the original // Find the search content in the original
@@ -130,39 +130,32 @@ Your search/replace content here
const currentIndentMatch = line.match(/^[\t ]*/); const currentIndentMatch = line.match(/^[\t ]*/);
const currentIndent = currentIndentMatch ? currentIndentMatch[0] : ''; const currentIndent = currentIndentMatch ? currentIndentMatch[0] : '';
// If this line has the same indentation level as the search block, // Get the corresponding search line's indentation
// use the original indentation. Otherwise, calculate the difference const searchLineIndex = Math.min(i, searchLines.length - 1);
// and preserve the exact type of whitespace characters const searchLineIndent = searchIndents[searchLineIndex];
if (currentIndent.length === searchIndent.length) {
return originalIndent + line.trim();
} else {
// Get the corresponding search line's indentation
const searchLineIndex = Math.min(i, searchLines.length - 1);
const searchLineIndent = searchIndents[searchLineIndex];
// Get the corresponding original line's indentation // Get the corresponding original line's indentation
const originalLineIndex = Math.min(i, originalIndents.length - 1); const originalLineIndex = Math.min(i, originalIndents.length - 1);
const originalLineIndent = originalIndents[originalLineIndex]; const originalLineIndent = originalIndents[originalLineIndex];
// If this line has the same indentation as its corresponding search line, // If this line has the same indentation as its corresponding search line,
// use the original indentation // use the original indentation
if (currentIndent === searchLineIndent) { if (currentIndent === searchLineIndent) {
return originalLineIndent + line.trim(); return originalLineIndent + line.trim();
}
// Otherwise, preserve the original indentation structure
const indentChar = originalLineIndent.charAt(0) || '\t';
const indentLevel = Math.floor(originalLineIndent.length / indentChar.length);
// Calculate the relative indentation from the search line
const searchLevel = Math.floor(searchLineIndent.length / indentChar.length);
const currentLevel = Math.floor(currentIndent.length / indentChar.length);
const relativeLevel = currentLevel - searchLevel;
// Apply the relative indentation to the original level
const targetLevel = Math.max(0, indentLevel + relativeLevel);
return indentChar.repeat(targetLevel) + line.trim();
} }
// Otherwise, preserve the original indentation structure
const indentChar = originalLineIndent.charAt(0) || '\t';
const indentLevel = Math.floor(originalLineIndent.length / indentChar.length);
// Calculate the relative indentation from the search line
const searchLevel = Math.floor(searchLineIndent.length / indentChar.length);
const currentLevel = Math.floor(currentIndent.length / indentChar.length);
const relativeLevel = currentLevel - searchLevel;
// Apply the relative indentation to the original level
const targetLevel = Math.max(0, indentLevel + relativeLevel);
return indentChar.repeat(targetLevel) + line.trim();
}); });
// Construct the final content // Construct the final content