mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 12:15:42 +02:00
preserve variable capture spans in blocks (#15334)
Closes #15160 # User-Facing Changes Certain "variable not found" errors no longer highlight the surrounding block. Before: ```nushell do { match foo { _ => $in } } Error: nu:🐚:variable_not_found × Variable not found ╭─[entry #1:1:1] 1 │ ╭─▶ do { 2 │ │ match foo { 3 │ │ _ => $in 4 │ │ } 5 │ ├─▶ } · ╰──── variable not found ``` After: ```nushell Error: nu:🐚:variable_not_found × Variable not found ╭─[entry #1:3:10] 2 │ match foo { 3 │ _ => $in · ─┬─ · ╰── variable not found ```
This commit is contained in:
@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||
pub struct Block {
|
||||
pub signature: Box<Signature>,
|
||||
pub pipelines: Vec<Pipeline>,
|
||||
pub captures: Vec<VarId>,
|
||||
pub captures: Vec<(VarId, Span)>,
|
||||
pub redirect_env: bool,
|
||||
/// The block compiled to IR instructions. Not available for subexpressions.
|
||||
pub ir_block: Option<IrBlock>,
|
||||
|
@ -111,7 +111,10 @@ impl Expression {
|
||||
Expr::UnaryNot(expr) => expr.has_in_variable(working_set),
|
||||
Expr::Block(block_id) | Expr::Closure(block_id) => {
|
||||
let block = working_set.get_block(*block_id);
|
||||
block.captures.contains(&IN_VARIABLE_ID)
|
||||
block
|
||||
.captures
|
||||
.iter()
|
||||
.any(|(var_id, _)| var_id == &IN_VARIABLE_ID)
|
||||
|| block
|
||||
.pipelines
|
||||
.iter()
|
||||
|
@ -322,12 +322,12 @@ impl Stack {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gather_captures(&self, engine_state: &EngineState, captures: &[VarId]) -> Stack {
|
||||
pub fn gather_captures(&self, engine_state: &EngineState, captures: &[(VarId, Span)]) -> Stack {
|
||||
let mut vars = Vec::with_capacity(captures.len());
|
||||
|
||||
let fake_span = Span::new(0, 0);
|
||||
|
||||
for capture in captures {
|
||||
for (capture, _) in captures {
|
||||
// Note: this assumes we have calculated captures correctly and that commands
|
||||
// that take in a var decl will manually set this into scope when running the blocks
|
||||
if let Ok(value) = self.get_var(*capture, fake_span) {
|
||||
|
Reference in New Issue
Block a user