fix(tui): highlight C++ module files (#28554)

## Why

Codex syntax-highlights diffs for conventional C++ extensions such as
`.cpp` and `.cxx`, but C++ module interface files using `.cppm`, `.ixx`,
or `.cxxm` fall back to plain diff coloring. The bundled syntax set
already includes C++, but it does not resolve those module extensions by
itself.

Closes #28223.

## What changed

- map `.cppm`, `.ixx`, and `.cxxm` to the existing `cpp` syntax in
`render/highlight.rs`
- extend alias-resolution coverage for all three module extensions
- verify `.cpp`, `.cppm`, `.ixx`, and `.cxxm` diffs produce
syntax-highlighted RGB spans while unknown extensions retain the plain
fallback
- snapshot the syntax-colored token segmentation for the supported C++
module extensions

## How to Test

1. Ask Codex to create or modify a C++ module interface file using
`.cppm`, `.ixx`, or `.cxxm`.
2. Confirm C++ tokens in the rendered diff receive syntax colors instead
of only the red/green diff treatment.
3. Modify an equivalent `.cpp` file and confirm its existing
highlighting remains unchanged.
4. Modify a file with an unknown extension and confirm it still uses the
plain diff fallback.

Targeted tests:

- `just test -p codex-tui -E
'test(find_syntax_resolves_languages_and_aliases) |
test(cpp_module_extensions_use_cpp_highlighting) |
test(unknown_extension_falls_back_without_syntax_highlighting)'`
This commit is contained in:
Felipe Coury
2026-06-16 17:33:13 +00:00
committed by GitHub
parent a376781a3c
commit 3ded846488
3 changed files with 94 additions and 2 deletions
+53
View File
@@ -1307,6 +1307,7 @@ fn style_gutter_dim() -> Style {
#[cfg(test)]
mod tests {
use super::*;
use insta::assert_debug_snapshot;
use insta::assert_snapshot;
use pretty_assertions::assert_eq;
use ratatui::Terminal;
@@ -2200,6 +2201,58 @@ mod tests {
);
}
#[test]
fn cpp_module_extensions_use_cpp_highlighting() {
let highlighted_tokens = ["cpp", "cppm", "CPPM", "cxxm", "CxXm", "ixx", "IXX"]
.into_iter()
.map(|extension| {
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();
changes.insert(
PathBuf::from(format!("math.{extension}")),
FileChange::Add {
content:
"export module math;\nexport int sum(int a, int b) { return a + b; }\n"
.to_string(),
},
);
let lines =
create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80);
let rgb_tokens = lines
.iter()
.flat_map(|line| &line.spans)
.filter(|span| matches!(span.style.fg, Some(ratatui::style::Color::Rgb(..))))
.map(|span| span.content.to_string())
.collect::<Vec<_>>();
assert!(
!rgb_tokens.is_empty(),
"add diff for .{extension} file should produce syntax-highlighted (RGB) spans"
);
(extension, rgb_tokens.join("|"))
})
.collect::<Vec<_>>();
assert_debug_snapshot!("cpp_module_extension_highlighting", highlighted_tokens);
}
#[test]
fn unknown_extension_falls_back_without_syntax_highlighting() {
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();
changes.insert(
PathBuf::from("math.unknown-extension"),
FileChange::Add {
content: "export module math;\nexport int value = 42;\n".to_string(),
},
);
let lines = create_diff_summary(&changes, &PathBuf::from("/"), /*wrap_cols*/ 80);
assert!(lines.iter().all(|line| {
line.spans
.iter()
.all(|span| !matches!(span.style.fg, Some(ratatui::style::Color::Rgb(..))))
}));
}
#[test]
fn delete_diff_uses_path_extension_for_highlighting() {
let mut changes: HashMap<PathBuf, FileChange> = HashMap::new();