search: fix faulty replacements in crlf files with lf regex (#168124)

Fixes https://github.com/microsoft/vscode/issues/165700

Regex normalization was actually working fine (finally). The issue was
JS code was matching again to do the replacement. If the original regex
only was written for LF, but the file was CRLF, VS Code did not attempt
to normalize line feeds until it tried to pull the surrounding content
as well as a 'last resort'.

If the surrounding content included a match before the intended one,
then that would be used instead, resulting in the bug.

PR does a small style change to add early returns to avoid nesting.
This commit is contained in:
Connor Peet 2022-12-06 08:30:40 -08:00 committed by GitHub
parent dac409ee91
commit 3b4ff94607
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -109,25 +109,37 @@ export class Match {
const fullMatchText = this.fullMatchText();
let replaceString = searchModel.replacePattern.getReplaceString(fullMatchText, searchModel.preserveCase);
if (replaceString !== null) {
return replaceString;
}
// Search/find normalize line endings - check whether \r prevents regex from matching
const fullMatchTextWithoutCR = fullMatchText.replace(/\r\n/g, '\n');
if (fullMatchTextWithoutCR !== fullMatchText) {
replaceString = searchModel.replacePattern.getReplaceString(fullMatchTextWithoutCR, searchModel.preserveCase);
if (replaceString !== null) {
return replaceString;
}
}
// If match string is not matching then regex pattern has a lookahead expression
if (replaceString === null) {
const fullMatchTextWithSurroundingContent = this.fullMatchText(true);
replaceString = searchModel.replacePattern.getReplaceString(fullMatchTextWithSurroundingContent, searchModel.preserveCase);
const contextMatchTextWithSurroundingContent = this.fullMatchText(true);
replaceString = searchModel.replacePattern.getReplaceString(contextMatchTextWithSurroundingContent, searchModel.preserveCase);
if (replaceString !== null) {
return replaceString;
}
// Search/find normalize line endings - check whether \r prevents regex from matching
if (replaceString === null) {
const fullMatchTextWithoutCR = fullMatchTextWithSurroundingContent.replace(/\r\n/g, '\n');
replaceString = searchModel.replacePattern.getReplaceString(fullMatchTextWithoutCR, searchModel.preserveCase);
// Search/find normalize line endings, this time in full context
const contextMatchTextWithoutCR = contextMatchTextWithSurroundingContent.replace(/\r\n/g, '\n');
if (contextMatchTextWithoutCR !== contextMatchTextWithSurroundingContent) {
replaceString = searchModel.replacePattern.getReplaceString(contextMatchTextWithoutCR, searchModel.preserveCase);
if (replaceString !== null) {
return replaceString;
}
}
// Match string is still not matching. Could be unsupported matches (multi-line).
if (replaceString === null) {
replaceString = searchModel.replacePattern.pattern;
}
return replaceString;
return searchModel.replacePattern.pattern;
}
fullMatchText(includeSurrounding = false): string {