mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-09 22:31:08 +00:00
fix: remove omission detection logic to fix false positives (#9787)
Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
parent
23605bed93
commit
86edc01cb1
4 changed files with 0 additions and 195 deletions
|
|
@ -11,7 +11,6 @@ import { fileExistsAtPath, createDirectoriesForFile } from "../../utils/fs"
|
|||
import { stripLineNumbers, everyLineHasLineNumbers } from "../../integrations/misc/extract-text"
|
||||
import { getReadablePath } from "../../utils/path"
|
||||
import { isPathOutsideWorkspace } from "../../utils/pathUtils"
|
||||
import { detectCodeOmission } from "../../integrations/editor/detect-omission"
|
||||
import { unescapeHtmlEntities } from "../../utils/text-normalization"
|
||||
import { DEFAULT_WRITE_DELAY_MS } from "@roo-code/types"
|
||||
import { EXPERIMENT_IDS, experiments } from "../../shared/experiments"
|
||||
|
|
@ -125,32 +124,6 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
|
|||
task.diffViewProvider.originalContent = ""
|
||||
}
|
||||
|
||||
if (detectCodeOmission(task.diffViewProvider.originalContent || "", newContent)) {
|
||||
if (task.diffStrategy) {
|
||||
pushToolResult(
|
||||
formatResponse.toolError(
|
||||
`Content appears to contain comments indicating omitted code (e.g., '// rest of code unchanged', '/* previous code */'). Please provide the complete file content without any omissions if possible, or otherwise use the 'apply_diff' tool to apply the diff to the original file.`,
|
||||
),
|
||||
)
|
||||
return
|
||||
} else {
|
||||
vscode.window
|
||||
.showWarningMessage(
|
||||
"Potential code truncation detected. This happens when the AI reaches its max output limit.",
|
||||
"Follow guide to fix the issue",
|
||||
)
|
||||
.then((selection) => {
|
||||
if (selection === "Follow guide to fix the issue") {
|
||||
vscode.env.openExternal(
|
||||
vscode.Uri.parse(
|
||||
"https://github.com/cline/cline/wiki/Troubleshooting-%E2%80%90-Cline-Deleting-Code-with-%22Rest-of-Code-Here%22-Comments",
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let unified = fileExists
|
||||
? formatResponse.createPrettyPatch(relPath, task.diffViewProvider.originalContent, newContent)
|
||||
: convertNewFileToUnifiedDiff(newContent, relPath)
|
||||
|
|
@ -183,34 +156,6 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
|
|||
await delay(300)
|
||||
task.diffViewProvider.scrollToFirstDiff()
|
||||
|
||||
if (detectCodeOmission(task.diffViewProvider.originalContent || "", newContent)) {
|
||||
if (task.diffStrategy) {
|
||||
await task.diffViewProvider.revertChanges()
|
||||
|
||||
pushToolResult(
|
||||
formatResponse.toolError(
|
||||
`Content appears to contain comments indicating omitted code (e.g., '// rest of code unchanged', '/* previous code */'). Please provide the complete file content without any omissions if possible, or otherwise use the 'apply_diff' tool to apply the diff to the original file.`,
|
||||
),
|
||||
)
|
||||
return
|
||||
} else {
|
||||
vscode.window
|
||||
.showWarningMessage(
|
||||
"Potential code truncation detected. This happens when the AI reaches its max output limit.",
|
||||
"Follow guide to fix the issue",
|
||||
)
|
||||
.then((selection) => {
|
||||
if (selection === "Follow guide to fix the issue") {
|
||||
vscode.env.openExternal(
|
||||
vscode.Uri.parse(
|
||||
"https://github.com/cline/cline/wiki/Troubleshooting-%E2%80%90-Cline-Deleting-Code-with-%22Rest-of-Code-Here%22-Comments",
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let unified = fileExists
|
||||
? formatResponse.createPrettyPatch(relPath, task.diffViewProvider.originalContent, newContent)
|
||||
: convertNewFileToUnifiedDiff(newContent, relPath)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import * as path from "path"
|
|||
import type { MockedFunction } from "vitest"
|
||||
|
||||
import { fileExistsAtPath, createDirectoriesForFile } from "../../../utils/fs"
|
||||
import { detectCodeOmission } from "../../../integrations/editor/detect-omission"
|
||||
import { isPathOutsideWorkspace } from "../../../utils/pathUtils"
|
||||
import { getReadablePath } from "../../../utils/path"
|
||||
import { unescapeHtmlEntities } from "../../../utils/text-normalization"
|
||||
|
|
@ -40,10 +39,6 @@ vi.mock("../../prompts/responses", () => ({
|
|||
},
|
||||
}))
|
||||
|
||||
vi.mock("../../../integrations/editor/detect-omission", () => ({
|
||||
detectCodeOmission: vi.fn().mockReturnValue(false),
|
||||
}))
|
||||
|
||||
vi.mock("../../../utils/pathUtils", () => ({
|
||||
isPathOutsideWorkspace: vi.fn().mockReturnValue(false),
|
||||
}))
|
||||
|
|
@ -100,7 +95,6 @@ describe("writeToFileTool", () => {
|
|||
// Mocked functions with correct types
|
||||
const mockedFileExistsAtPath = fileExistsAtPath as MockedFunction<typeof fileExistsAtPath>
|
||||
const mockedCreateDirectoriesForFile = createDirectoriesForFile as MockedFunction<typeof createDirectoriesForFile>
|
||||
const mockedDetectCodeOmission = detectCodeOmission as MockedFunction<typeof detectCodeOmission>
|
||||
const mockedIsPathOutsideWorkspace = isPathOutsideWorkspace as MockedFunction<typeof isPathOutsideWorkspace>
|
||||
const mockedGetReadablePath = getReadablePath as MockedFunction<typeof getReadablePath>
|
||||
const mockedUnescapeHtmlEntities = unescapeHtmlEntities as MockedFunction<typeof unescapeHtmlEntities>
|
||||
|
|
@ -120,7 +114,6 @@ describe("writeToFileTool", () => {
|
|||
|
||||
mockedPathResolve.mockReturnValue(absoluteFilePath)
|
||||
mockedFileExistsAtPath.mockResolvedValue(false)
|
||||
mockedDetectCodeOmission.mockReturnValue(false)
|
||||
mockedIsPathOutsideWorkspace.mockReturnValue(false)
|
||||
mockedGetReadablePath.mockReturnValue("test/path.txt")
|
||||
mockedUnescapeHtmlEntities.mockImplementation((content) => content)
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
import { detectCodeOmission } from "../detect-omission"
|
||||
|
||||
describe("detectCodeOmission", () => {
|
||||
const originalContent = `function example() {
|
||||
// Some code
|
||||
const x = 1;
|
||||
const y = 2;
|
||||
return x + y;
|
||||
}`
|
||||
|
||||
// Generate content with a specified number of lines (100+ lines triggers detection)
|
||||
const generateLongContent = (commentLine: string, length: number = 110) => {
|
||||
return `${commentLine}
|
||||
${Array.from({ length }, (_, i) => `const x${i} = ${i};`).join("\n")}
|
||||
const y = 2;`
|
||||
}
|
||||
|
||||
it("should skip comment checks for files under 100 lines", () => {
|
||||
const newContent = `// Lines 1-50 remain unchanged
|
||||
const z = 3;`
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(false)
|
||||
})
|
||||
|
||||
it("should not detect regular comments without omission keywords", () => {
|
||||
const newContent = generateLongContent("// Adding new functionality")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(false)
|
||||
})
|
||||
|
||||
it("should not detect when comment is part of original content", () => {
|
||||
const originalWithComment = `// Content remains unchanged
|
||||
${originalContent}`
|
||||
const newContent = generateLongContent("// Content remains unchanged")
|
||||
expect(detectCodeOmission(originalWithComment, newContent)).toBe(false)
|
||||
})
|
||||
|
||||
it("should not detect code that happens to contain omission keywords", () => {
|
||||
const newContent = generateLongContent(`const remains = 'some value';
|
||||
const unchanged = true;`)
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(false)
|
||||
})
|
||||
|
||||
it("should detect suspicious single-line comment for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent("// Previous content remains here\nconst x = 1;")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should detect suspicious Python-style comment for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent("# Previous content remains here\nconst x = 1;")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should detect suspicious multi-line comment for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent("/* Previous content remains the same */\nconst x = 1;")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should detect suspicious JSX comment for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent("{/* Rest of the code remains the same */}\nconst x = 1;")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should detect suspicious HTML comment for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent("<!-- Existing content unchanged -->\nconst x = 1;")
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should detect suspicious square bracket notation for files with 100+ lines", () => {
|
||||
const newContent = generateLongContent(
|
||||
"[Previous content from line 1-305 remains exactly the same]\nconst x = 1;",
|
||||
)
|
||||
expect(detectCodeOmission(originalContent, newContent)).toBe(true)
|
||||
})
|
||||
|
||||
it("should not flag legitimate comments in files with 100+ lines when in original", () => {
|
||||
const originalWithComment = `// This is a legitimate comment that remains here
|
||||
${originalContent}`
|
||||
const newContent = generateLongContent("// This is a legitimate comment that remains here")
|
||||
expect(detectCodeOmission(originalWithComment, newContent)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* Detects potential AI-generated code omissions in the given file content.
|
||||
* Looks for comments containing omission keywords that weren't in the original file.
|
||||
* @param originalFileContent The original content of the file.
|
||||
* @param newFileContent The new content of the file to check.
|
||||
* @returns True if a potential omission is detected, false otherwise.
|
||||
*/
|
||||
export function detectCodeOmission(originalFileContent: string, newFileContent: string): boolean {
|
||||
const actualLineCount = newFileContent.split("\n").length
|
||||
|
||||
// Skip checks for small files (less than 100 lines)
|
||||
if (actualLineCount < 100) {
|
||||
return false
|
||||
}
|
||||
|
||||
const originalLines = originalFileContent.split("\n")
|
||||
const newLines = newFileContent.split("\n")
|
||||
const omissionKeywords = [
|
||||
"remain",
|
||||
"remains",
|
||||
"unchanged",
|
||||
"rest",
|
||||
"previous",
|
||||
"existing",
|
||||
"content",
|
||||
"same",
|
||||
"...",
|
||||
]
|
||||
|
||||
const commentPatterns = [
|
||||
/^\s*\/\//, // Single-line comment for most languages
|
||||
/^\s*#/, // Single-line comment for Python, Ruby, etc.
|
||||
/^\s*\/\*/, // Multi-line comment opening
|
||||
/^\s*{\s*\/\*/, // JSX comment opening
|
||||
/^\s*<!--/, // HTML comment opening
|
||||
/^\s*\[/, // Square bracket notation
|
||||
]
|
||||
|
||||
// Consider comments as suspicious if they weren't in the original file
|
||||
// and contain omission keywords
|
||||
for (const line of newLines) {
|
||||
if (commentPatterns.some((pattern) => pattern.test(line))) {
|
||||
const words = line.toLowerCase().split(/\s+/)
|
||||
if (omissionKeywords.some((keyword) => words.includes(keyword))) {
|
||||
if (!originalLines.includes(line)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue