Warn (not error) on identical search-replace blocks and include searc… (#1899)
…h-replace failure in error message Addresses part of #1898 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Treat identical SEARCH/REPLACE as a no-op warning and propagate detailed applySearchReplace errors (incl. fuzzy match stats) to the UI; add scoped logging and update tests/snapshots. > > - **Processors**: > - `src/pro/main/ipc/processors/search_replace_processor.ts`: Log a warning (not error) when SEARCH and REPLACE blocks are identical; add scoped logger; keep content unchanged. > - `src/ipc/processors/response_processor.ts`: Include detailed failure reason from `applySearchReplace` in dry-run issues. > - **Tests & Snapshots**: > - `search_replace_processor.spec.ts`: Update test to expect success when blocks are identical. > - `e2e-tests/...turbo-edits-v2...snapshot`: Reflect detailed error message with fuzzy match similarity/threshold. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit a394d297d5561ada3bdd197dbb4e6aca6928ad99. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Warn instead of error when search and replace blocks are identical, and include the specific failure reason in search-replace error messages for clearer feedback. - **Bug Fixes** - Treat identical search/replace blocks as a no-op: log a warning and return success. - Bubble up detailed failure reasons to the UI (e.g., no match and fuzzy similarity/threshold). - Add scoped logging to the processor and update the e2e snapshot to reflect new error messaging. <sup>Written for commit a394d297d5561ada3bdd197dbb4e6aca6928ad99. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
@@ -229,8 +229,8 @@ function example() {
|
||||
expect(content).not.toContain("start();");
|
||||
});
|
||||
|
||||
it("errors when SEARCH and REPLACE blocks are identical", () => {
|
||||
const original = ["x", "y", "z"].join("\n");
|
||||
it("not an error when SEARCH and REPLACE blocks are identical", () => {
|
||||
const original = ["x", "middle", "z"].join("\n");
|
||||
const diff = `
|
||||
<<<<<<< SEARCH
|
||||
middle
|
||||
@@ -238,9 +238,9 @@ middle
|
||||
middle
|
||||
>>>>>>> REPLACE
|
||||
`;
|
||||
const { success, error } = applySearchReplace(original, diff);
|
||||
expect(success).toBe(false);
|
||||
expect(error).toMatch(/Search and replace blocks are identical/i);
|
||||
const { success, content } = applySearchReplace(original, diff);
|
||||
expect(success).toBe(true);
|
||||
expect(content).toBe(original);
|
||||
});
|
||||
|
||||
it("errors when SEARCH block matches multiple locations (ambiguous)", () => {
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
import { parseSearchReplaceBlocks } from "@/pro/shared/search_replace_parser";
|
||||
import { distance } from "fastest-levenshtein";
|
||||
import { normalizeString } from "@/utils/text_normalization";
|
||||
import log from "electron-log";
|
||||
|
||||
const logger = log.scope("search_replace_processor");
|
||||
|
||||
// Minimum similarity threshold for fuzzy matching (0 to 1, where 1 is exact match)
|
||||
const FUZZY_MATCH_THRESHOLD = 0.9;
|
||||
@@ -201,12 +204,9 @@ export function applySearchReplace(
|
||||
};
|
||||
}
|
||||
|
||||
// If search and replace are identical, it's a no-op and should be treated as an error
|
||||
// If search and replace are identical, it's a no-op and is just treated as a warning
|
||||
if (searchLines.join("\n") === replaceLines.join("\n")) {
|
||||
return {
|
||||
success: false,
|
||||
error: "Search and replace blocks are identical",
|
||||
};
|
||||
logger.warn("Search and replace blocks are identical");
|
||||
}
|
||||
|
||||
let matchIndex = -1;
|
||||
|
||||
Reference in New Issue
Block a user