Skip to content

fix: preserve indentation when applying code edits to Python files#11289

Open
mvanhorn wants to merge 1 commit intocontinuedev:mainfrom
mvanhorn:fix/python-indentation-edit
Open

fix: preserve indentation when applying code edits to Python files#11289
mvanhorn wants to merge 1 commit intocontinuedev:mainfrom
mvanhorn:fix/python-indentation-edit

Conversation

@mvanhorn
Copy link
Contributor

@mvanhorn mvanhorn commented Mar 11, 2026

Summary

  • When the code edit tool uses fallback matching strategies (trimmedMatch, whitespaceIgnoredMatch) to find a match, the replacement string's indentation is now adjusted to match the actual indentation level in the file
  • This fixes Python code edits where the LLM provides search/replace strings with different indentation than the target code, resulting in broken indentation after the edit

How it works

  • adjustReplacementIndentation() detects the leading whitespace of the matched text in the file and the LLM-provided old_string
  • If they differ (indicating a fuzzy match with different indentation), each line of new_string is re-indented: the old indent prefix is stripped and replaced with the matched indent
  • Exact matches are passed through unchanged, preserving existing behavior

Test plan

  • Verify Python files with indented code blocks are edited correctly when the LLM provides unindented search/replace strings
  • Verify exact match replacements still work as before (no indentation adjustment)
  • Verify replaceAll mode also applies indentation normalization

Fixes #11282

🤖 Generated with Claude Code


Summary by cubic

Preserves indentation when applying fuzzy-matched code edits so Python blocks remain valid. Re-indents the replacement text to match the file’s actual indent level.

  • Bug Fixes
    • Detects leading indent of matched text and re-indents each line of newString when it differs from the oldString.
    • Applies to both single replacements and replaceAll.
    • Skips adjustment for exact/empty matches to keep current behavior.

Written for commit 70b6b17. Summary will update on new commits.

When fallback matching strategies (trimmedMatch, whitespaceIgnoredMatch)
find a match with different indentation than the LLM-provided old_string,
the replacement new_string now has its indentation adjusted to match the
actual indentation level in the file. This fixes incorrect indentation in
Python code edits where the LLM provides unindented search/replace strings
that match indented code blocks.

Fixes continuedev#11282

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mvanhorn mvanhorn requested a review from a team as a code owner March 11, 2026 06:16
@mvanhorn mvanhorn requested review from Patrick-Erichsen and removed request for a team March 11, 2026 06:16
@mvanhorn
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@dosubot dosubot bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Mar 11, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="core/edit/searchAndReplace/performReplace.ts">

<violation number="1" location="core/edit/searchAndReplace/performReplace.ts:58">
P2: First replacement line can remain unindented when `oldIndent` is non-empty, because fallback indentation adjustment only runs for `oldIndent === ""`.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

// For lines that don't start with the old indent (e.g. first line
// might have no indent if old_string was trimmed), apply the
// matched indent directly
if (index === 0 && oldIndent === "" && matchedIndent !== "") {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: First replacement line can remain unindented when oldIndent is non-empty, because fallback indentation adjustment only runs for oldIndent === "".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At core/edit/searchAndReplace/performReplace.ts, line 58:

<comment>First replacement line can remain unindented when `oldIndent` is non-empty, because fallback indentation adjustment only runs for `oldIndent === ""`.</comment>

<file context>
@@ -1,6 +1,67 @@
+    // For lines that don't start with the old indent (e.g. first line
+    // might have no indent if old_string was trimmed), apply the
+    // matched indent directly
+    if (index === 0 && oldIndent === "" && matchedIndent !== "") {
+      return matchedIndent + line;
+    }
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

The code modification tool has incorrect indentation on Python

1 participant