Fix circular variable dependency error message (#909)

This commit is contained in:
Casey Rodarmor 2021-07-19 18:10:35 -07:00 committed by GitHub
parent 6cf3d204e6
commit 0fea73455b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 30 additions and 23 deletions

View File

@ -5,7 +5,6 @@ use CompilationErrorKind::*;
pub(crate) struct AssignmentResolver<'src: 'run, 'run> {
assignments: &'run Table<'src, Assignment<'src>>,
stack: Vec<&'src str>,
seen: BTreeSet<&'src str>,
evaluated: BTreeSet<&'src str>,
}
@ -14,9 +13,8 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
assignments: &Table<'src, Assignment<'src>>,
) -> CompilationResult<'src, ()> {
let mut resolver = AssignmentResolver {
stack: empty(),
seen: empty(),
evaluated: empty(),
stack: Vec::new(),
evaluated: BTreeSet::new(),
assignments,
};
@ -32,7 +30,6 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
return Ok(());
}
self.seen.insert(name);
self.stack.push(name);
if let Some(assignment) = self.assignments.get(name) {
@ -53,6 +50,9 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
token,
});
}
self.stack.pop();
Ok(())
}
@ -62,7 +62,7 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
let variable = name.lexeme();
if self.evaluated.contains(variable) {
Ok(())
} else if self.seen.contains(variable) {
} else if self.stack.contains(&variable) {
let token = self.assignments[variable].name.token();
self.stack.push(variable);
Err(token.error(CircularVariableDependency {

View File

@ -41,21 +41,21 @@ impl Color {
pub(crate) fn auto() -> Self {
Self {
use_color: UseColor::Auto,
..default()
..Color::default()
}
}
pub(crate) fn always() -> Self {
Self {
use_color: UseColor::Always,
..default()
..Color::default()
}
}
pub(crate) fn never() -> Self {
Self {
use_color: UseColor::Never,
..default()
..Color::default()
}
}

View File

@ -33,9 +33,7 @@ pub(crate) use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
pub(crate) use crate::{config_error, setting};
// functions
pub(crate) use crate::{
default::default, empty::empty, load_dotenv::load_dotenv, output::output, unindent::unindent,
};
pub(crate) use crate::{load_dotenv::load_dotenv, output::output, unindent::unindent};
// traits
pub(crate) use crate::{

View File

@ -1,3 +0,0 @@
pub(crate) fn default<T: Default>() -> T {
Default::default()
}

View File

@ -1,5 +0,0 @@
use crate::common::*;
pub(crate) fn empty<T, C: iter::FromIterator<T>>() -> C {
iter::empty().collect()
}

View File

@ -71,10 +71,8 @@ mod compiler;
mod config;
mod config_error;
mod count;
mod default;
mod delimiter;
mod dependency;
mod empty;
mod enclosure;
mod error;
mod error_result_ext;

View File

@ -14,7 +14,7 @@ impl<'src: 'run, 'run> RecipeResolver<'src, 'run> {
assignments: &Table<'src, Assignment<'src>>,
) -> CompilationResult<'src, Table<'src, Rc<Recipe<'src>>>> {
let mut resolver = RecipeResolver {
resolved_recipes: empty(),
resolved_recipes: Table::new(),
unresolved_recipes,
assignments,
};

View File

@ -1410,6 +1410,25 @@ test! {
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! {
name: plus_variadic_recipe,
justfile: "