fix: limit \r\n escape preprocessing to anchor/find params only
normalizeContentLineEndings 在 8e637db7 引入的 \r\n escape 预处理对
所有调用路径生效,导致 workspaceWrite 写入 C 源码时破坏 \r\n 字符串常量。
修复:增加 unescapeEscapeSequences 参数(默认 false),仅在
workspaceReplace find、workspaceInsertAfter anchor、diagnosticDetails
三个 anchor 匹配路径启用 escape 预处理。
- workspaceWrite content: 不启用(保留原始 \r\n)
- workspaceReplace replace text: 不启用
- workspaceInsertAfter insertText: 不启用
- applyUpdateHunks output: 不启用(已是规范化内容)
Fixes #1027
This commit is contained in:
@@ -419,7 +419,7 @@ async function workspaceReplace(args: any) {
|
||||
assertExpectedSha(before, args.expectedSha, relativePath);
|
||||
const find = requiredRawString(args.find, "find");
|
||||
const replace = rawString(args.replace ?? args.replacement);
|
||||
const normalizedFind = normalizeContentLineEndings(find, "\n", false);
|
||||
const normalizedFind = normalizeContentLineEndings(find, "\n", false, true);
|
||||
const normalizedReplace = normalizeContentLineEndings(replace, "\n", false);
|
||||
const normalizedContent = before.normalizedContent;
|
||||
const occurrences = countOccurrences(normalizedContent, normalizedFind);
|
||||
@@ -443,7 +443,7 @@ async function workspaceInsertAfter(args: any) {
|
||||
assertExpectedSha(before, args.expectedSha, relativePath);
|
||||
const anchor = requiredRawString(args.anchor, "anchor");
|
||||
const insertText = requiredRawString(args.line ?? args.insert ?? args.text, "line");
|
||||
const normalizedAnchor = normalizeContentLineEndings(anchor, "\n", false);
|
||||
const normalizedAnchor = normalizeContentLineEndings(anchor, "\n", false, true);
|
||||
const normalizedInsert = normalizeContentLineEndings(insertText, "\n", false);
|
||||
const lines = splitNormalizedLines(before.normalizedContent, before.hadFinalNewline);
|
||||
const anchorLines = splitNormalizedLines(normalizedAnchor, false);
|
||||
@@ -611,7 +611,7 @@ function splitNormalizedLines(content: string, hadFinalNewline: boolean) {
|
||||
}
|
||||
|
||||
function diagnosticDetails(fileState: any, expected: string, relativePath: string) {
|
||||
const expectedLines = splitNormalizedLines(normalizeContentLineEndings(expected, "\n", false), false).filter((line) => line.length > 0);
|
||||
const expectedLines = splitNormalizedLines(normalizeContentLineEndings(expected, "\n", false, true), false).filter((line) => line.length > 0);
|
||||
const normalizedLines = splitNormalizedLines(fileState.normalizedContent, fileState.hadFinalNewline);
|
||||
const candidates = expectedLines.slice(0, 4).flatMap((line) => candidateLines(normalizedLines, line)).slice(0, 12);
|
||||
return {
|
||||
@@ -700,9 +700,9 @@ function lineEndingFromArgs(args: any, fallback: string) {
|
||||
throw cliError("invalid_line_ending", "lineEnding must be preserve, lf, or crlf", { lineEnding: value });
|
||||
}
|
||||
|
||||
function normalizeContentLineEndings(content: string, lineEnding: string, finalNewline: boolean) {
|
||||
const unescaped = String(content).replace(/\\r\\n/gu, "\r\n").replace(/\\n/gu, "\n").replace(/\\r(?!\n)/gu, "\r");
|
||||
const normalized = unescaped.replace(/\r\n?/gu, "\n");
|
||||
function normalizeContentLineEndings(content: string, lineEnding: string, finalNewline: boolean, unescapeEscapeSequences = false) {
|
||||
const base = unescapeEscapeSequences ? String(content).replace(/\\r\\n/gu, "\r\n").replace(/\\n/gu, "\n").replace(/\\r(?!\n)/gu, "\r") : String(content);
|
||||
const normalized = base.replace(/\r\n?/gu, "\n");
|
||||
const withFinal = finalNewline && !normalized.endsWith("\n") ? `${normalized}\n` : normalized;
|
||||
return lineEnding === "\r\n" ? withFinal.replace(/\n/gu, "\r\n") : withFinal;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user