mirror of
https://github.com/nushell/nushell.git
synced 2025-03-26 07:19:55 +01:00
Add support for var decl spans (#4787)
This commit is contained in:
parent
4ddf24269a
commit
2ac990655e
@ -2,8 +2,8 @@ use nu_engine::CallExt;
|
|||||||
use nu_protocol::ast::{Call, Expr, Expression};
|
use nu_protocol::ast::{Call, Expr, Expression};
|
||||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
Category, DataSource, Example, IntoPipelineData, PipelineData, PipelineMetadata, Signature,
|
Category, DataSource, Example, IntoPipelineData, PipelineData, PipelineMetadata, ShellError,
|
||||||
Span, SyntaxShape, Value,
|
Signature, Span, SyntaxShape, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -41,7 +41,6 @@ impl Command for Metadata {
|
|||||||
match arg {
|
match arg {
|
||||||
Some(Expression {
|
Some(Expression {
|
||||||
expr: Expr::FullCellPath(full_cell_path),
|
expr: Expr::FullCellPath(full_cell_path),
|
||||||
span,
|
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
if full_cell_path.tail.is_empty() {
|
if full_cell_path.tail.is_empty() {
|
||||||
@ -50,25 +49,30 @@ impl Command for Metadata {
|
|||||||
expr: Expr::Var(var_id),
|
expr: Expr::Var(var_id),
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let origin = stack.get_var_with_origin(*var_id, *span)?;
|
let variable = engine_state.get_var(*var_id);
|
||||||
|
|
||||||
Ok(build_metadata_record(&origin, &input.metadata(), head)
|
Ok(build_metadata_record(
|
||||||
.into_pipeline_data())
|
Ok(variable.declaration_span),
|
||||||
|
&input.metadata(),
|
||||||
|
head,
|
||||||
|
)
|
||||||
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let val: Value = call.req(engine_state, stack, 0)?;
|
let val: Value = call.req(engine_state, stack, 0)?;
|
||||||
Ok(build_metadata_record(&val, &input.metadata(), head)
|
Ok(build_metadata_record(val.span(), &input.metadata(), head)
|
||||||
.into_pipeline_data())
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let val: Value = call.req(engine_state, stack, 0)?;
|
let val: Value = call.req(engine_state, stack, 0)?;
|
||||||
Ok(build_metadata_record(&val, &input.metadata(), head).into_pipeline_data())
|
Ok(build_metadata_record(val.span(), &input.metadata(), head)
|
||||||
|
.into_pipeline_data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let val: Value = call.req(engine_state, stack, 0)?;
|
let val: Value = call.req(engine_state, stack, 0)?;
|
||||||
Ok(build_metadata_record(&val, &input.metadata(), head).into_pipeline_data())
|
Ok(build_metadata_record(val.span(), &input.metadata(), head).into_pipeline_data())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
@ -113,11 +117,15 @@ impl Command for Metadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_metadata_record(arg: &Value, metadata: &Option<PipelineMetadata>, head: Span) -> Value {
|
fn build_metadata_record(
|
||||||
|
span: Result<Span, ShellError>,
|
||||||
|
metadata: &Option<PipelineMetadata>,
|
||||||
|
head: Span,
|
||||||
|
) -> Value {
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut vals = vec![];
|
let mut vals = vec![];
|
||||||
|
|
||||||
if let Ok(span) = arg.span() {
|
if let Ok(span) = span {
|
||||||
cols.push("span".into());
|
cols.push("span".into());
|
||||||
vals.push(Value::Record {
|
vals.push(Value::Record {
|
||||||
cols: vec!["start".into(), "end".into()],
|
cols: vec!["start".into(), "end".into()],
|
||||||
|
@ -761,7 +761,7 @@ pub fn create_scope(
|
|||||||
for var in &frame.vars {
|
for var in &frame.vars {
|
||||||
let var_name = Value::string(String::from_utf8_lossy(var.0).to_string(), span);
|
let var_name = Value::string(String::from_utf8_lossy(var.0).to_string(), span);
|
||||||
|
|
||||||
let var_type = Value::string(engine_state.get_var(*var.1).to_string(), span);
|
let var_type = Value::string(engine_state.get_var(*var.1).ty.to_string(), span);
|
||||||
|
|
||||||
let var_value = if let Ok(val) = stack.get_var(*var.1, span) {
|
let var_value = if let Ok(val) = stack.get_var(*var.1, span) {
|
||||||
val
|
val
|
||||||
|
@ -1596,7 +1596,7 @@ pub fn parse_variable_expr(
|
|||||||
Expression {
|
Expression {
|
||||||
expr: Expr::Var(id),
|
expr: Expr::Var(id),
|
||||||
span,
|
span,
|
||||||
ty: working_set.get_variable(id).clone(),
|
ty: working_set.get_variable(id).ty.clone(),
|
||||||
custom_completion: None,
|
custom_completion: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
@ -2632,7 +2632,11 @@ pub fn parse_var_with_opt_type(
|
|||||||
|
|
||||||
let ty = parse_type(working_set, type_bytes);
|
let ty = parse_type(working_set, type_bytes);
|
||||||
|
|
||||||
let id = working_set.add_variable(bytes[0..(bytes.len() - 1)].to_vec(), ty.clone());
|
let id = working_set.add_variable(
|
||||||
|
bytes[0..(bytes.len() - 1)].to_vec(),
|
||||||
|
spans[*spans_idx - 1],
|
||||||
|
ty.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
@ -2644,7 +2648,11 @@ pub fn parse_var_with_opt_type(
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let id = working_set.add_variable(bytes[0..(bytes.len() - 1)].to_vec(), Type::Unknown);
|
let id = working_set.add_variable(
|
||||||
|
bytes[0..(bytes.len() - 1)].to_vec(),
|
||||||
|
spans[*spans_idx],
|
||||||
|
Type::Unknown,
|
||||||
|
);
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
expr: Expr::VarDecl(id),
|
expr: Expr::VarDecl(id),
|
||||||
@ -2666,7 +2674,11 @@ pub fn parse_var_with_opt_type(
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let id = working_set.add_variable(bytes, Type::Unknown);
|
let id = working_set.add_variable(
|
||||||
|
bytes,
|
||||||
|
span(&spans[*spans_idx..*spans_idx + 1]),
|
||||||
|
Type::Unknown,
|
||||||
|
);
|
||||||
|
|
||||||
(
|
(
|
||||||
Expression {
|
Expression {
|
||||||
@ -2702,7 +2714,7 @@ pub fn parse_row_condition(
|
|||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
) -> (Expression, Option<ParseError>) {
|
) -> (Expression, Option<ParseError>) {
|
||||||
let var_id = working_set.add_variable(b"$it".to_vec(), Type::Unknown);
|
let var_id = working_set.add_variable(b"$it".to_vec(), span(spans), Type::Unknown);
|
||||||
let (expression, err) = parse_math_expression(working_set, spans, Some(var_id));
|
let (expression, err) = parse_math_expression(working_set, spans, Some(var_id));
|
||||||
let span = span(spans);
|
let span = span(spans);
|
||||||
|
|
||||||
@ -2858,7 +2870,8 @@ pub fn parse_signature_helper(
|
|||||||
|
|
||||||
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
||||||
let variable_name = flags[0][2..].to_vec();
|
let variable_name = flags[0][2..].to_vec();
|
||||||
let var_id = working_set.add_variable(variable_name, Type::Unknown);
|
let var_id =
|
||||||
|
working_set.add_variable(variable_name, span, Type::Unknown);
|
||||||
|
|
||||||
if flags.len() == 1 {
|
if flags.len() == 1 {
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
@ -2888,8 +2901,11 @@ pub fn parse_signature_helper(
|
|||||||
let chars: Vec<char> = short_flag.chars().collect();
|
let chars: Vec<char> = short_flag.chars().collect();
|
||||||
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
||||||
let variable_name = flags[0][2..].to_vec();
|
let variable_name = flags[0][2..].to_vec();
|
||||||
let var_id =
|
let var_id = working_set.add_variable(
|
||||||
working_set.add_variable(variable_name, Type::Unknown);
|
variable_name,
|
||||||
|
span,
|
||||||
|
Type::Unknown,
|
||||||
|
);
|
||||||
|
|
||||||
if chars.len() == 1 {
|
if chars.len() == 1 {
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
@ -2923,7 +2939,8 @@ pub fn parse_signature_helper(
|
|||||||
let mut encoded_var_name = vec![0u8; 4];
|
let mut encoded_var_name = vec![0u8; 4];
|
||||||
let len = chars[0].encode_utf8(&mut encoded_var_name).len();
|
let len = chars[0].encode_utf8(&mut encoded_var_name).len();
|
||||||
let variable_name = encoded_var_name[0..len].to_vec();
|
let variable_name = encoded_var_name[0..len].to_vec();
|
||||||
let var_id = working_set.add_variable(variable_name, Type::Unknown);
|
let var_id =
|
||||||
|
working_set.add_variable(variable_name, span, Type::Unknown);
|
||||||
|
|
||||||
args.push(Arg::Flag(Flag {
|
args.push(Arg::Flag(Flag {
|
||||||
arg: None,
|
arg: None,
|
||||||
@ -2981,7 +2998,8 @@ pub fn parse_signature_helper(
|
|||||||
let contents: Vec<_> = contents[..(contents.len() - 1)].into();
|
let contents: Vec<_> = contents[..(contents.len() - 1)].into();
|
||||||
let name = String::from_utf8_lossy(&contents).to_string();
|
let name = String::from_utf8_lossy(&contents).to_string();
|
||||||
|
|
||||||
let var_id = working_set.add_variable(contents, Type::Unknown);
|
let var_id =
|
||||||
|
working_set.add_variable(contents, span, Type::Unknown);
|
||||||
|
|
||||||
// Positional arg, optional
|
// Positional arg, optional
|
||||||
args.push(Arg::Positional(
|
args.push(Arg::Positional(
|
||||||
@ -2998,7 +3016,8 @@ pub fn parse_signature_helper(
|
|||||||
let name = String::from_utf8_lossy(contents).to_string();
|
let name = String::from_utf8_lossy(contents).to_string();
|
||||||
let contents_vec: Vec<u8> = contents.to_vec();
|
let contents_vec: Vec<u8> = contents.to_vec();
|
||||||
|
|
||||||
let var_id = working_set.add_variable(contents_vec, Type::Unknown);
|
let var_id =
|
||||||
|
working_set.add_variable(contents_vec, span, Type::Unknown);
|
||||||
|
|
||||||
args.push(Arg::RestPositional(PositionalArg {
|
args.push(Arg::RestPositional(PositionalArg {
|
||||||
desc: String::new(),
|
desc: String::new(),
|
||||||
@ -3011,7 +3030,8 @@ pub fn parse_signature_helper(
|
|||||||
let name = String::from_utf8_lossy(contents).to_string();
|
let name = String::from_utf8_lossy(contents).to_string();
|
||||||
let contents_vec = contents.to_vec();
|
let contents_vec = contents.to_vec();
|
||||||
|
|
||||||
let var_id = working_set.add_variable(contents_vec, Type::Unknown);
|
let var_id =
|
||||||
|
working_set.add_variable(contents_vec, span, Type::Unknown);
|
||||||
|
|
||||||
// Positional arg, required
|
// Positional arg, required
|
||||||
args.push(Arg::Positional(
|
args.push(Arg::Positional(
|
||||||
@ -3072,7 +3092,7 @@ pub fn parse_signature_helper(
|
|||||||
required,
|
required,
|
||||||
) => {
|
) => {
|
||||||
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
||||||
let var_type = working_set.get_variable(var_id);
|
let var_type = &working_set.get_variable(var_id).ty;
|
||||||
match var_type {
|
match var_type {
|
||||||
Type::Unknown => {
|
Type::Unknown => {
|
||||||
working_set.set_variable_type(
|
working_set.set_variable_type(
|
||||||
@ -3112,7 +3132,7 @@ pub fn parse_signature_helper(
|
|||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
let var_id = var_id.expect("internal error: all custom parameters must have var_ids");
|
||||||
let var_type = working_set.get_variable(var_id);
|
let var_type = &working_set.get_variable(var_id).ty;
|
||||||
|
|
||||||
let expression_ty = expression.ty.clone();
|
let expression_ty = expression.ty.clone();
|
||||||
let expression_span = expression.span;
|
let expression_span = expression.span;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::{Command, Stack};
|
use super::{Command, Stack};
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::Block, AliasId, BlockId, DeclId, Example, Overlay, OverlayId, ShellError, Signature, Span,
|
ast::Block, AliasId, BlockId, DeclId, Example, Overlay, OverlayId, ShellError, Signature, Span,
|
||||||
Type, VarId,
|
Type, VarId, Variable,
|
||||||
};
|
};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::{
|
use std::{
|
||||||
@ -159,7 +159,7 @@ impl Default for ScopeFrame {
|
|||||||
pub struct EngineState {
|
pub struct EngineState {
|
||||||
files: im::Vector<(String, usize, usize)>,
|
files: im::Vector<(String, usize, usize)>,
|
||||||
file_contents: im::Vector<(Vec<u8>, usize, usize)>,
|
file_contents: im::Vector<(Vec<u8>, usize, usize)>,
|
||||||
vars: im::Vector<Type>,
|
vars: im::Vector<Variable>,
|
||||||
decls: im::Vector<Box<dyn Command + 'static>>,
|
decls: im::Vector<Box<dyn Command + 'static>>,
|
||||||
aliases: im::Vector<Vec<Span>>,
|
aliases: im::Vector<Vec<Span>>,
|
||||||
blocks: im::Vector<Block>,
|
blocks: im::Vector<Block>,
|
||||||
@ -186,11 +186,11 @@ impl EngineState {
|
|||||||
files: im::vector![],
|
files: im::vector![],
|
||||||
file_contents: im::vector![],
|
file_contents: im::vector![],
|
||||||
vars: im::vector![
|
vars: im::vector![
|
||||||
Type::Unknown,
|
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||||
Type::Unknown,
|
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||||
Type::Unknown,
|
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||||
Type::Unknown,
|
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||||
Type::Unknown
|
Variable::new(Span::new(0, 0), Type::Unknown)
|
||||||
],
|
],
|
||||||
decls: im::vector![],
|
decls: im::vector![],
|
||||||
aliases: im::vector![],
|
aliases: im::vector![],
|
||||||
@ -481,7 +481,7 @@ impl EngineState {
|
|||||||
panic!("internal error: span missing in file contents cache")
|
panic!("internal error: span missing in file contents cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_var(&self, var_id: VarId) -> &Type {
|
pub fn get_var(&self, var_id: VarId) -> &Variable {
|
||||||
self.vars
|
self.vars
|
||||||
.get(var_id)
|
.get(var_id)
|
||||||
.expect("internal error: missing variable")
|
.expect("internal error: missing variable")
|
||||||
@ -655,7 +655,7 @@ pub struct StateWorkingSet<'a> {
|
|||||||
pub struct StateDelta {
|
pub struct StateDelta {
|
||||||
files: Vec<(String, usize, usize)>,
|
files: Vec<(String, usize, usize)>,
|
||||||
pub(crate) file_contents: Vec<(Vec<u8>, usize, usize)>,
|
pub(crate) file_contents: Vec<(Vec<u8>, usize, usize)>,
|
||||||
vars: Vec<Type>, // indexed by VarId
|
vars: Vec<Variable>, // indexed by VarId
|
||||||
decls: Vec<Box<dyn Command>>, // indexed by DeclId
|
decls: Vec<Box<dyn Command>>, // indexed by DeclId
|
||||||
aliases: Vec<Vec<Span>>, // indexed by AliasId
|
aliases: Vec<Vec<Span>>, // indexed by AliasId
|
||||||
pub blocks: Vec<Block>, // indexed by BlockId
|
pub blocks: Vec<Block>, // indexed by BlockId
|
||||||
@ -1136,7 +1136,7 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_variable(&mut self, mut name: Vec<u8>, ty: Type) -> VarId {
|
pub fn add_variable(&mut self, mut name: Vec<u8>, span: Span, ty: Type) -> VarId {
|
||||||
let next_id = self.next_var_id();
|
let next_id = self.next_var_id();
|
||||||
|
|
||||||
// correct name if necessary
|
// correct name if necessary
|
||||||
@ -1152,7 +1152,7 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
|
|
||||||
last.vars.insert(name, next_id);
|
last.vars.insert(name, next_id);
|
||||||
|
|
||||||
self.delta.vars.push(ty);
|
self.delta.vars.push(Variable::new(span, ty));
|
||||||
|
|
||||||
next_id
|
next_id
|
||||||
}
|
}
|
||||||
@ -1185,11 +1185,11 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
if var_id < num_permanent_vars {
|
if var_id < num_permanent_vars {
|
||||||
panic!("Internal error: attempted to set into permanent state from working set")
|
panic!("Internal error: attempted to set into permanent state from working set")
|
||||||
} else {
|
} else {
|
||||||
self.delta.vars[var_id - num_permanent_vars] = ty;
|
self.delta.vars[var_id - num_permanent_vars].ty = ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_variable(&self, var_id: VarId) -> &Type {
|
pub fn get_variable(&self, var_id: VarId) -> &Variable {
|
||||||
let num_permanent_vars = self.permanent_state.num_vars();
|
let num_permanent_vars = self.permanent_state.num_vars();
|
||||||
if var_id < num_permanent_vars {
|
if var_id < num_permanent_vars {
|
||||||
self.permanent_state.get_var(var_id)
|
self.permanent_state.get_var(var_id)
|
||||||
|
@ -12,7 +12,7 @@ mod span;
|
|||||||
mod syntax_shape;
|
mod syntax_shape;
|
||||||
mod ty;
|
mod ty;
|
||||||
mod value;
|
mod value;
|
||||||
pub use value::Value;
|
mod variable;
|
||||||
|
|
||||||
pub use config::*;
|
pub use config::*;
|
||||||
pub use engine::{CONFIG_VARIABLE_ID, ENV_VARIABLE_ID, IN_VARIABLE_ID, NU_VARIABLE_ID};
|
pub use engine::{CONFIG_VARIABLE_ID, ENV_VARIABLE_ID, IN_VARIABLE_ID, NU_VARIABLE_ID};
|
||||||
@ -26,5 +26,5 @@ pub use signature::*;
|
|||||||
pub use span::*;
|
pub use span::*;
|
||||||
pub use syntax_shape::*;
|
pub use syntax_shape::*;
|
||||||
pub use ty::*;
|
pub use ty::*;
|
||||||
pub use value::CustomValue;
|
|
||||||
pub use value::*;
|
pub use value::*;
|
||||||
|
pub use variable::*;
|
||||||
|
16
crates/nu-protocol/src/variable.rs
Normal file
16
crates/nu-protocol/src/variable.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use crate::{Span, Type};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Variable {
|
||||||
|
pub declaration_span: Span,
|
||||||
|
pub ty: Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Variable {
|
||||||
|
pub fn new(declaration_span: Span, ty: Type) -> Variable {
|
||||||
|
Self {
|
||||||
|
declaration_span,
|
||||||
|
ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user