mirror of
https://github.com/openai/codex.git
synced 2026-04-29 00:55:38 +00:00
4.8 KiB
4.8 KiB
DOs
- Multiple context lines: Parse all leading
@@lines intochunk.context_linesand advancestart_indexaccordingly.
// parser.rs
let mut context_lines = Vec::new();
let mut start_index = 0;
while start_index < lines.len() {
if let Some(ctx) = lines[start_index].strip_prefix(CHANGE_CONTEXT_MARKER) {
context_lines.push(ctx.to_string());
start_index += 1;
} else if lines[start_index] == EMPTY_CHANGE_CONTEXT_MARKER {
start_index += 1;
} else {
break;
}
}
- Sequential seeking: Find each context line in order and advance
line_indexafter every match; fail with an informative error.
// lib.rs
for (i, ctx) in chunk.context_lines.iter().enumerate() {
if let Some(idx) = seek_sequence::seek_sequence(
original_lines,
std::slice::from_ref(ctx),
line_index,
false,
) {
line_index = idx + 1;
} else {
return Err(ApplyPatchError::ComputeReplacements(
format!("Failed to find context {}/{}: '{}' in {}",
i + 1, chunk.context_lines.len(), ctx, path.display())
));
}
}
- Context‑aware insertion: For pure additions, insert after the last matched context when not end‑of‑file; otherwise append (respect trailing blank line).
let insertion_idx = if !chunk.is_end_of_file && !chunk.context_lines.is_empty() {
line_index
} else if original_lines.last().is_some_and(|s| s.is_empty()) {
original_lines.len() - 1
} else {
original_lines.len()
};
- Chunk order: Treat the first context line of each chunk as the ordering anchor that must appear after the previous chunk.
/// Chunks are in file order: the first context line of
/// each chunk must occur later in the file than the previous chunk.
- Precise errors: Include which context failed (index/total), the text, and the path; inline variables with
format!.
return Err(ApplyPatchError::ComputeReplacements(
format!("Failed to find context {}/{}: '{}' in {}",
i + 1, total, ctx_line, path.display())
));
- Accurate line numbers: When reporting parser errors after consuming context markers, offset by
start_index.
return Err(InvalidHunkError {
message: "Update hunk does not contain any lines".to_string(),
line_number: line_number + start_index,
});
- Tests for anchors: Cover single and multi‑context insertion to ensure additions land immediately after the final context.
assert_eq!(
contents,
"class BaseClass:\n def method():\nINSERTED\nline1\n"
);
- Newline at EOF: End JSON fixtures (and other text files) with a trailing newline.
[
{ "type": "response.output_item.done", "item": { "type": "custom_tool_call", "name": "apply_patch", "input": "...", "call_id": "__ID__" } },
{ "type": "response.completed", "response": { "id": "__ID__", "usage": { "input_tokens": 0, "output_tokens": 0, "total_tokens": 0 }, "output": [] } }
]
- Cross‑platform tests: Prefer unguarded tests and early‑exit via env checks instead of OS gating unless truly necessary.
#[tokio::test]
async fn test_apply_patch_context() -> anyhow::Result<()> {
use codex_core::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
if std::env::var(CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR).is_ok() {
return Ok(());
}
// run_e2e_exec_test(...);
Ok(())
}
DON’Ts
- Single‑context assumption: Don’t stop after the first
@@; handle multiple context lines.
// Wrong: only considers a single context line
let change_context = lines[0].strip_prefix(CHANGE_CONTEXT_MARKER)
.map(|s| s.to_string());
- Unanchored additions: Don’t append pure additions to EOF when a context anchor exists and the hunk isn’t EOF.
// Wrong: ignores matched context when not EOF
let insertion_idx = original_lines.len();
- Vague errors: Don’t omit which context failed or the path.
// Wrong: not actionable
return Err(err("Failed to find context"));
- Off‑by‑one line numbers: Don’t report errors relative to the first line of the hunk after consuming context markers.
// Wrong: loses offset from consumed @@ lines
line_number: line_number + 1,
- Unnecessary Windows gating: Don’t
#[cfg(not(target_os = "windows"))]tests that aren’t OS‑specific; prefer capability/env checks.
// Wrong: hides a portable test for no reason
#[cfg(not(target_os = "windows"))]
#[tokio::test]
async fn test_apply_patch_context() { /* ... */ }
- Missing EOF newline: Don’t check in fixtures without a final newline.
{ "type": "response.completed" }[] // Wrong: no trailing newline and malformed
- Ignoring chunk order: Don’t assume chunk contexts can search backwards or overlap arbitrarily.
// Wrong: resets search to 0; may match earlier occurrences
line_index = 0; // Do not do this between chunks