fix(natives): resolved bash for extensionless shell rc files

blockRangeAt inferred no language for files like `zshrc`/`.zshrc`/`.bashrc`
because `Path::extension` returns `None` for bare and dotfile names alike,
so the edit tool's `replace block` / `insert after block` ops were
permanently unresolvable on them — an agent retrying the block op would
loop on the same "could not resolve a syntactic block" error.

from_extension now maps known shell rc/profile basenames (zshrc, zshenv,
zprofile, zlogin, zlogout, zsh_aliases, bashrc, bash_profile, bash_login,
bash_logout, bash_aliases, profile, kshrc, mkshrc, shrc; with or without a
leading dot) to the bash grammar, alongside the existing Makefile/Dockerfile
basename handling. Adds a block-resolution regression test over a zsh
`if [[ … ]]; then … fi` block in `zshrc`/`.zshrc`/`.bashrc`.
This commit is contained in:
bling
2026-06-11 20:36:54 -04:00
parent 31c5b21204
commit 79fe2134e9
3 changed files with 42 additions and 0 deletions
+13
View File
@@ -298,6 +298,19 @@ mod tests {
assert_eq!(resolve(TS_EXAMPLE, "x.unknownext", 2), None);
}
#[test]
fn resolves_zsh_if_block_in_extensionless_rc_file() {
// Regression: an extensionless shell rc file (`zshrc`/`.zshrc`) must
// infer the bash grammar so `replace block` / `insert after block`
// works. Previously `Path::extension` returned `None`, leaving block
// ops permanently unresolvable on these files.
let code = "ZSH_COMPDUMP=x\nif [[ -f \"$ZSH_COMPDUMP\" ]]; then\n compinit -C\nelse\n compinit\nfi\n";
let span = Some(BlockRange { start_line: 2, end_line: 6 });
assert_eq!(resolve(code, "modules/zsh/zshrc", 2), span);
assert_eq!(resolve(code, ".zshrc", 2), span);
assert_eq!(resolve(code, "/home/u/.bashrc", 2), span);
}
#[test]
fn resolves_top_level_python_def() {
let code = "x = 1\ndef greet():\n return 1\n";
+25
View File
@@ -627,6 +627,31 @@ fn from_extension(path: &Path) -> Option<SupportLang> {
return Some(SupportLang::Dockerfile);
}
// Extensionless shell rc/profile files. `Path::extension` returns `None`
// for both bare (`zshrc`) and dotfile (`.zshrc`) forms, so they would
// otherwise resolve to no language and disable block-aware ops on them.
let stem = name.strip_prefix('.').unwrap_or(name);
if matches!(
stem,
"zshrc"
| "zshenv"
| "zprofile"
| "zlogin"
| "zlogout"
| "zsh_aliases"
| "bashrc"
| "bash_profile"
| "bash_login"
| "bash_logout"
| "bash_aliases"
| "profile"
| "kshrc"
| "mkshrc"
| "shrc"
) {
return Some(SupportLang::Bash);
}
let ext = path.extension()?.to_str()?;
SupportLang::all_langs()
.iter()
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Fixed `blockRangeAt` (and thus the edit tool's `replace block` / `insert after block` ops) failing on extensionless shell rc/profile files. `Path::extension` returns `None` for both bare (`zshrc`) and dotfile (`.zshrc`, `.bashrc`) forms, so language inference fell through to "unrecognized" and block resolution was permanently unresolvable on those files — an agent retrying the block op would loop on the same error. Known shell rc/profile basenames (`zshrc`/`zshenv`/`zprofile`/`zlogin`/`zlogout`/`bashrc`/`bash_profile`/`bash_login`/`bash_logout`/`bash_aliases`/`profile`/`kshrc`/`mkshrc`/`shrc`, with or without a leading dot) now resolve to the bash grammar.
## [15.11.0] - 2026-06-10
### Breaking Changes