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

View File

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

View File

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

View File

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

View File

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

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