Add support for var decl spans (#4787)

This commit is contained in:
JT 2022-03-09 04:42:19 -05:00 committed by GitHub
parent 4ddf24269a
commit 2ac990655e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 85 additions and 41 deletions

View File

@ -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()],

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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::*;

View 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,
}
}
}