mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 14:15:53 +02:00
Forbid reserved variable names for function arguments (#11169)
Works for all arguments and flags. Because the signature parsing doesn't give the spans, it is flags the entire signature. Also added a constant with reserved variable names. Fix #11158.
This commit is contained in:
@ -40,6 +40,8 @@ use crate::{
|
||||
/// These parser keywords can be aliased
|
||||
pub const ALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[b"overlay hide", b"overlay new", b"overlay use"];
|
||||
|
||||
pub const RESERVED_VARIABLE_NAMES: [&str; 3] = ["in", "nu", "env"];
|
||||
|
||||
/// These parser keywords cannot be aliased (either not possible, or support not yet added)
|
||||
pub const UNALIASABLE_PARSER_KEYWORDS: &[&[u8]] = &[
|
||||
b"export",
|
||||
@ -350,6 +352,13 @@ pub fn parse_for(working_set: &mut StateWorkingSet, spans: &[Span]) -> Expressio
|
||||
}
|
||||
}
|
||||
|
||||
/// If `name` is a keyword, emit an error.
|
||||
fn verify_not_reserved_variable_name(working_set: &mut StateWorkingSet, name: &str, span: Span) {
|
||||
if RESERVED_VARIABLE_NAMES.contains(&name) {
|
||||
working_set.error(ParseError::NameIsBuiltinVar(name.to_string(), span))
|
||||
}
|
||||
}
|
||||
|
||||
// Returns also the parsed command name and ID
|
||||
pub fn parse_def(
|
||||
working_set: &mut StateWorkingSet,
|
||||
@ -515,6 +524,19 @@ pub fn parse_def(
|
||||
let mut result = None;
|
||||
|
||||
if let (Some(mut signature), Some(block_id)) = (sig.as_signature(), block.as_block()) {
|
||||
for arg_name in &signature.required_positional {
|
||||
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
|
||||
}
|
||||
for arg_name in &signature.optional_positional {
|
||||
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
|
||||
}
|
||||
for arg_name in &signature.rest_positional {
|
||||
verify_not_reserved_variable_name(working_set, &arg_name.name, sig.span);
|
||||
}
|
||||
for flag_name in &signature.get_names() {
|
||||
verify_not_reserved_variable_name(working_set, flag_name, sig.span);
|
||||
}
|
||||
|
||||
if has_wrapped {
|
||||
if let Some(rest) = &signature.rest_positional {
|
||||
if let Some(var_id) = rest.var_id {
|
||||
@ -2997,7 +3019,7 @@ pub fn parse_let(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
|
||||
.trim_start_matches('$')
|
||||
.to_string();
|
||||
|
||||
if ["in", "nu", "env"].contains(&var_name.as_str()) {
|
||||
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
|
||||
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
|
||||
}
|
||||
|
||||
@ -3104,8 +3126,7 @@ pub fn parse_const(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipelin
|
||||
.trim_start_matches('$')
|
||||
.to_string();
|
||||
|
||||
// TODO: Remove the hard-coded variables, too error-prone
|
||||
if ["in", "nu", "env"].contains(&var_name.as_str()) {
|
||||
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
|
||||
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
|
||||
}
|
||||
|
||||
@ -3246,7 +3267,7 @@ pub fn parse_mut(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
|
||||
.trim_start_matches('$')
|
||||
.to_string();
|
||||
|
||||
if ["in", "nu", "env"].contains(&var_name.as_str()) {
|
||||
if RESERVED_VARIABLE_NAMES.contains(&var_name.as_str()) {
|
||||
working_set.error(ParseError::NameIsBuiltinVar(var_name, lvalue.span))
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user