forked from extern/nushell
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::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, DataSource, Example, IntoPipelineData, PipelineData, PipelineMetadata, Signature,
|
||||
Span, SyntaxShape, Value,
|
||||
Category, DataSource, Example, IntoPipelineData, PipelineData, PipelineMetadata, ShellError,
|
||||
Signature, Span, SyntaxShape, Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -41,7 +41,6 @@ impl Command for Metadata {
|
||||
match arg {
|
||||
Some(Expression {
|
||||
expr: Expr::FullCellPath(full_cell_path),
|
||||
span,
|
||||
..
|
||||
}) => {
|
||||
if full_cell_path.tail.is_empty() {
|
||||
@ -50,25 +49,30 @@ impl Command for Metadata {
|
||||
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)
|
||||
.into_pipeline_data())
|
||||
Ok(build_metadata_record(
|
||||
Ok(variable.declaration_span),
|
||||
&input.metadata(),
|
||||
head,
|
||||
)
|
||||
.into_pipeline_data())
|
||||
}
|
||||
_ => {
|
||||
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())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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(_) => {
|
||||
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 => {
|
||||
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 vals = vec![];
|
||||
|
||||
if let Ok(span) = arg.span() {
|
||||
if let Ok(span) = span {
|
||||
cols.push("span".into());
|
||||
vals.push(Value::Record {
|
||||
cols: vec!["start".into(), "end".into()],
|
||||
|
@ -761,7 +761,7 @@ pub fn create_scope(
|
||||
for var in &frame.vars {
|
||||
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) {
|
||||
val
|
||||
|
@ -1596,7 +1596,7 @@ pub fn parse_variable_expr(
|
||||
Expression {
|
||||
expr: Expr::Var(id),
|
||||
span,
|
||||
ty: working_set.get_variable(id).clone(),
|
||||
ty: working_set.get_variable(id).ty.clone(),
|
||||
custom_completion: None,
|
||||
},
|
||||
None,
|
||||
@ -2632,7 +2632,11 @@ pub fn parse_var_with_opt_type(
|
||||
|
||||
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 {
|
||||
@ -2644,7 +2648,11 @@ pub fn parse_var_with_opt_type(
|
||||
None,
|
||||
)
|
||||
} 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 {
|
||||
expr: Expr::VarDecl(id),
|
||||
@ -2666,7 +2674,11 @@ pub fn parse_var_with_opt_type(
|
||||
None,
|
||||
)
|
||||
} 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 {
|
||||
@ -2702,7 +2714,7 @@ pub fn parse_row_condition(
|
||||
working_set: &mut StateWorkingSet,
|
||||
spans: &[Span],
|
||||
) -> (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 span = span(spans);
|
||||
|
||||
@ -2858,7 +2870,8 @@ pub fn parse_signature_helper(
|
||||
|
||||
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
||||
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 {
|
||||
args.push(Arg::Flag(Flag {
|
||||
@ -2888,8 +2901,11 @@ pub fn parse_signature_helper(
|
||||
let chars: Vec<char> = short_flag.chars().collect();
|
||||
let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
|
||||
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 chars.len() == 1 {
|
||||
args.push(Arg::Flag(Flag {
|
||||
@ -2923,7 +2939,8 @@ pub fn parse_signature_helper(
|
||||
let mut encoded_var_name = vec![0u8; 4];
|
||||
let len = chars[0].encode_utf8(&mut encoded_var_name).len();
|
||||
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 {
|
||||
arg: None,
|
||||
@ -2981,7 +2998,8 @@ pub fn parse_signature_helper(
|
||||
let contents: Vec<_> = contents[..(contents.len() - 1)].into();
|
||||
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
|
||||
args.push(Arg::Positional(
|
||||
@ -2998,7 +3016,8 @@ pub fn parse_signature_helper(
|
||||
let name = String::from_utf8_lossy(contents).to_string();
|
||||
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 {
|
||||
desc: String::new(),
|
||||
@ -3011,7 +3030,8 @@ pub fn parse_signature_helper(
|
||||
let name = String::from_utf8_lossy(contents).to_string();
|
||||
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
|
||||
args.push(Arg::Positional(
|
||||
@ -3072,7 +3092,7 @@ pub fn parse_signature_helper(
|
||||
required,
|
||||
) => {
|
||||
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 {
|
||||
Type::Unknown => {
|
||||
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_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_span = expression.span;
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{Command, Stack};
|
||||
use crate::{
|
||||
ast::Block, AliasId, BlockId, DeclId, Example, Overlay, OverlayId, ShellError, Signature, Span,
|
||||
Type, VarId,
|
||||
Type, VarId, Variable,
|
||||
};
|
||||
use core::panic;
|
||||
use std::{
|
||||
@ -159,7 +159,7 @@ impl Default for ScopeFrame {
|
||||
pub struct EngineState {
|
||||
files: im::Vector<(String, 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>>,
|
||||
aliases: im::Vector<Vec<Span>>,
|
||||
blocks: im::Vector<Block>,
|
||||
@ -186,11 +186,11 @@ impl EngineState {
|
||||
files: im::vector![],
|
||||
file_contents: im::vector![],
|
||||
vars: im::vector![
|
||||
Type::Unknown,
|
||||
Type::Unknown,
|
||||
Type::Unknown,
|
||||
Type::Unknown,
|
||||
Type::Unknown
|
||||
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||
Variable::new(Span::new(0, 0), Type::Unknown),
|
||||
Variable::new(Span::new(0, 0), Type::Unknown)
|
||||
],
|
||||
decls: im::vector![],
|
||||
aliases: im::vector![],
|
||||
@ -481,7 +481,7 @@ impl EngineState {
|
||||
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
|
||||
.get(var_id)
|
||||
.expect("internal error: missing variable")
|
||||
@ -655,7 +655,7 @@ pub struct StateWorkingSet<'a> {
|
||||
pub struct StateDelta {
|
||||
files: Vec<(String, 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
|
||||
aliases: Vec<Vec<Span>>, // indexed by AliasId
|
||||
pub blocks: Vec<Block>, // indexed by BlockId
|
||||
@ -1136,7 +1136,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||
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();
|
||||
|
||||
// correct name if necessary
|
||||
@ -1152,7 +1152,7 @@ impl<'a> StateWorkingSet<'a> {
|
||||
|
||||
last.vars.insert(name, next_id);
|
||||
|
||||
self.delta.vars.push(ty);
|
||||
self.delta.vars.push(Variable::new(span, ty));
|
||||
|
||||
next_id
|
||||
}
|
||||
@ -1185,11 +1185,11 @@ impl<'a> StateWorkingSet<'a> {
|
||||
if var_id < num_permanent_vars {
|
||||
panic!("Internal error: attempted to set into permanent state from working set")
|
||||
} 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();
|
||||
if var_id < num_permanent_vars {
|
||||
self.permanent_state.get_var(var_id)
|
||||
|
@ -12,7 +12,7 @@ mod span;
|
||||
mod syntax_shape;
|
||||
mod ty;
|
||||
mod value;
|
||||
pub use value::Value;
|
||||
mod variable;
|
||||
|
||||
pub use config::*;
|
||||
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 syntax_shape::*;
|
||||
pub use ty::*;
|
||||
pub use value::CustomValue;
|
||||
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