From 647d4b95a839578d3cd149ceac697bc3ddd1c002 Mon Sep 17 00:00:00 2001 From: pandeylakshya207-max Date: Sat, 19 Sep 2026 00:23:59 +0530 Subject: [PATCH 1/2] Preserve replace string when match has no cased characters buildReplaceStringWithCasePreserved treated a match unchanged by toUpperCase() as uppercase, so matches made only of punctuation or digits caused the replace string to be uppercased. Return the pattern unchanged when the match contains no cased characters. Fixes #192168 --- src/vs/base/common/search.ts | 6 ++++++ .../contrib/find/test/browser/replacePattern.test.ts | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/vs/base/common/search.ts b/src/vs/base/common/search.ts index 3d036494cc29a..6bfa9d0988fb6 100644 --- a/src/vs/base/common/search.ts +++ b/src/vs/base/common/search.ts @@ -7,6 +7,12 @@ import * as strings from './strings.js'; export function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string { if (matches && (matches[0] !== '')) { + // The match has no cased characters (e.g. punctuation or digits), so there is + // no case to preserve and the replace pattern is used as-is. + if (matches[0].toLowerCase() === matches[0].toUpperCase()) { + return pattern; + } + const containsHyphens = validateSpecificSpecialCharacter(matches, pattern, '-'); const containsUnderscores = validateSpecificSpecialCharacter(matches, pattern, '_'); if (containsHyphens && !containsUnderscores) { diff --git a/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts b/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts index 26c65b3d8be8a..adf1f19411e03 100644 --- a/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts @@ -219,6 +219,11 @@ suite('Replace Pattern test', () => { assertReplace(['Foo_Bar-abc'], 'newfoo_newbar-abc', 'Newfoo_newbar-abc'); assertReplace(['foo_Bar'], 'newfoo_newbar', 'newfoo_Newbar'); assertReplace(['Foo_BAR'], 'newfoo_newbar', 'Newfoo_NEWBAR'); + // #192168 - matches without any cased characters have no case to preserve + assertReplace(['()'], 'fontSize: 20', 'fontSize: 20'); + assertReplace(['123'], 'Def', 'Def'); + assertReplace(['!'], 'someValue', 'someValue'); + assertReplace(['(', ')'], 'fontSize: 20', 'fontSize: 20'); }); test('preserve case', () => { @@ -250,5 +255,10 @@ suite('Replace Pattern test', () => { assertReplace(['Foo_Bar-abc'], 'newfoo_newbar-abc', 'Newfoo_newbar-abc'); assertReplace(['foo_Bar'], 'newfoo_newbar', 'newfoo_Newbar'); assertReplace(['foo_BAR'], 'newfoo_newbar', 'newfoo_NEWBAR'); + // #192168 - matches without any cased characters have no case to preserve + assertReplace(['()'], 'fontSize: 20', 'fontSize: 20'); + assertReplace(['123'], 'Def', 'Def'); + assertReplace(['!'], 'someValue', 'someValue'); + assertReplace(['(', ')'], 'fontSize: 20', 'fontSize: 20'); }); }); From fb2a976c72f2cc1077d4be58a895d10b90fb1ff9 Mon Sep 17 00:00:00 2001 From: pandeylakshya207-max Date: Sat, 19 Sep 2026 01:07:23 +0530 Subject: [PATCH 2/2] Address review feedback: condense comment, test separator recursion --- src/vs/base/common/search.ts | 3 +-- .../editor/contrib/find/test/browser/replacePattern.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/vs/base/common/search.ts b/src/vs/base/common/search.ts index 6bfa9d0988fb6..250b530c175ad 100644 --- a/src/vs/base/common/search.ts +++ b/src/vs/base/common/search.ts @@ -7,8 +7,7 @@ import * as strings from './strings.js'; export function buildReplaceStringWithCasePreserved(matches: string[] | null, pattern: string): string { if (matches && (matches[0] !== '')) { - // The match has no cased characters (e.g. punctuation or digits), so there is - // no case to preserve and the replace pattern is used as-is. + // A caseless match has no case to preserve, so use the pattern as-is. if (matches[0].toLowerCase() === matches[0].toUpperCase()) { return pattern; } diff --git a/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts b/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts index adf1f19411e03..7b7ab95235d8d 100644 --- a/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts +++ b/src/vs/editor/contrib/find/test/browser/replacePattern.test.ts @@ -223,7 +223,7 @@ suite('Replace Pattern test', () => { assertReplace(['()'], 'fontSize: 20', 'fontSize: 20'); assertReplace(['123'], 'Def', 'Def'); assertReplace(['!'], 'someValue', 'someValue'); - assertReplace(['(', ')'], 'fontSize: 20', 'fontSize: 20'); + assertReplace(['ABC-123'], 'Def-someValue', 'DEF-someValue'); }); test('preserve case', () => { @@ -259,6 +259,6 @@ suite('Replace Pattern test', () => { assertReplace(['()'], 'fontSize: 20', 'fontSize: 20'); assertReplace(['123'], 'Def', 'Def'); assertReplace(['!'], 'someValue', 'someValue'); - assertReplace(['(', ')'], 'fontSize: 20', 'fontSize: 20'); + assertReplace(['ABC-123'], 'Def-someValue', 'DEF-someValue'); }); });