Fix circular variable dependency error message (#909)
This commit is contained in:
parent
6cf3d204e6
commit
0fea73455b
@ -5,7 +5,6 @@ use CompilationErrorKind::*;
|
|||||||
pub(crate) struct AssignmentResolver<'src: 'run, 'run> {
|
pub(crate) struct AssignmentResolver<'src: 'run, 'run> {
|
||||||
assignments: &'run Table<'src, Assignment<'src>>,
|
assignments: &'run Table<'src, Assignment<'src>>,
|
||||||
stack: Vec<&'src str>,
|
stack: Vec<&'src str>,
|
||||||
seen: BTreeSet<&'src str>,
|
|
||||||
evaluated: BTreeSet<&'src str>,
|
evaluated: BTreeSet<&'src str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,9 +13,8 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
|||||||
assignments: &Table<'src, Assignment<'src>>,
|
assignments: &Table<'src, Assignment<'src>>,
|
||||||
) -> CompilationResult<'src, ()> {
|
) -> CompilationResult<'src, ()> {
|
||||||
let mut resolver = AssignmentResolver {
|
let mut resolver = AssignmentResolver {
|
||||||
stack: empty(),
|
stack: Vec::new(),
|
||||||
seen: empty(),
|
evaluated: BTreeSet::new(),
|
||||||
evaluated: empty(),
|
|
||||||
assignments,
|
assignments,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,7 +30,6 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.seen.insert(name);
|
|
||||||
self.stack.push(name);
|
self.stack.push(name);
|
||||||
|
|
||||||
if let Some(assignment) = self.assignments.get(name) {
|
if let Some(assignment) = self.assignments.get(name) {
|
||||||
@ -53,6 +50,9 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
|||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stack.pop();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
|||||||
let variable = name.lexeme();
|
let variable = name.lexeme();
|
||||||
if self.evaluated.contains(variable) {
|
if self.evaluated.contains(variable) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else if self.seen.contains(variable) {
|
} else if self.stack.contains(&variable) {
|
||||||
let token = self.assignments[variable].name.token();
|
let token = self.assignments[variable].name.token();
|
||||||
self.stack.push(variable);
|
self.stack.push(variable);
|
||||||
Err(token.error(CircularVariableDependency {
|
Err(token.error(CircularVariableDependency {
|
||||||
|
@ -41,21 +41,21 @@ impl Color {
|
|||||||
pub(crate) fn auto() -> Self {
|
pub(crate) fn auto() -> Self {
|
||||||
Self {
|
Self {
|
||||||
use_color: UseColor::Auto,
|
use_color: UseColor::Auto,
|
||||||
..default()
|
..Color::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn always() -> Self {
|
pub(crate) fn always() -> Self {
|
||||||
Self {
|
Self {
|
||||||
use_color: UseColor::Always,
|
use_color: UseColor::Always,
|
||||||
..default()
|
..Color::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn never() -> Self {
|
pub(crate) fn never() -> Self {
|
||||||
Self {
|
Self {
|
||||||
use_color: UseColor::Never,
|
use_color: UseColor::Never,
|
||||||
..default()
|
..Color::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +33,7 @@ pub(crate) use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
|||||||
pub(crate) use crate::{config_error, setting};
|
pub(crate) use crate::{config_error, setting};
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
pub(crate) use crate::{
|
pub(crate) use crate::{load_dotenv::load_dotenv, output::output, unindent::unindent};
|
||||||
default::default, empty::empty, load_dotenv::load_dotenv, output::output, unindent::unindent,
|
|
||||||
};
|
|
||||||
|
|
||||||
// traits
|
// traits
|
||||||
pub(crate) use crate::{
|
pub(crate) use crate::{
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
pub(crate) fn default<T: Default>() -> T {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
use crate::common::*;
|
|
||||||
|
|
||||||
pub(crate) fn empty<T, C: iter::FromIterator<T>>() -> C {
|
|
||||||
iter::empty().collect()
|
|
||||||
}
|
|
@ -71,10 +71,8 @@ mod compiler;
|
|||||||
mod config;
|
mod config;
|
||||||
mod config_error;
|
mod config_error;
|
||||||
mod count;
|
mod count;
|
||||||
mod default;
|
|
||||||
mod delimiter;
|
mod delimiter;
|
||||||
mod dependency;
|
mod dependency;
|
||||||
mod empty;
|
|
||||||
mod enclosure;
|
mod enclosure;
|
||||||
mod error;
|
mod error;
|
||||||
mod error_result_ext;
|
mod error_result_ext;
|
||||||
|
@ -14,7 +14,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> {
|
|||||||
assignments: &Table<'src, Assignment<'src>>,
|
assignments: &Table<'src, Assignment<'src>>,
|
||||||
) -> CompilationResult<'src, Table<'src, Rc<Recipe<'src>>>> {
|
) -> CompilationResult<'src, Table<'src, Rc<Recipe<'src>>>> {
|
||||||
let mut resolver = RecipeResolver {
|
let mut resolver = RecipeResolver {
|
||||||
resolved_recipes: empty(),
|
resolved_recipes: Table::new(),
|
||||||
unresolved_recipes,
|
unresolved_recipes,
|
||||||
assignments,
|
assignments,
|
||||||
};
|
};
|
||||||
|
@ -1410,6 +1410,25 @@ test! {
|
|||||||
status: EXIT_FAILURE,
|
status: EXIT_FAILURE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: variable_circular_dependency_with_additional_variable,
|
||||||
|
justfile: "
|
||||||
|
a := ''
|
||||||
|
x := y
|
||||||
|
y := x
|
||||||
|
|
||||||
|
a:
|
||||||
|
",
|
||||||
|
args: ("a"),
|
||||||
|
stdout: "",
|
||||||
|
stderr: "error: Variable `x` depends on its own value: `x -> y -> x`
|
||||||
|
|
|
||||||
|
2 | x := y
|
||||||
|
| ^
|
||||||
|
",
|
||||||
|
status: EXIT_FAILURE,
|
||||||
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: plus_variadic_recipe,
|
name: plus_variadic_recipe,
|
||||||
justfile: "
|
justfile: "
|
||||||
|
Loading…
Reference in New Issue
Block a user