Error -> CompileError (#97)

Fixes #43
This commit is contained in:
Casey Rodarmor 2016-11-12 14:24:33 -08:00 committed by GitHub
parent caf2570bb2
commit 1856646a9c
2 changed files with 93 additions and 91 deletions

View File

@ -424,7 +424,7 @@ fn resolve_recipes<'a>(
recipes: &Map<&'a str, Recipe<'a>>, recipes: &Map<&'a str, Recipe<'a>>,
assignments: &Map<&'a str, Expression<'a>>, assignments: &Map<&'a str, Expression<'a>>,
text: &'a str, text: &'a str,
) -> Result<(), Error<'a>> { ) -> Result<(), CompileError<'a>> {
let mut resolver = Resolver { let mut resolver = Resolver {
seen: Set::new(), seen: Set::new(),
stack: vec![], stack: vec![],
@ -455,7 +455,7 @@ fn resolve_recipes<'a>(
// of the struct, and the second being the lifetime of the tokens // of the struct, and the second being the lifetime of the tokens
// that it contains // that it contains
let error = variable.error(ErrorKind::UndefinedVariable{variable: name}); let error = variable.error(ErrorKind::UndefinedVariable{variable: name});
return Err(Error { return Err(CompileError {
text: text, text: text,
index: error.index, index: error.index,
line: error.line, line: error.line,
@ -483,7 +483,7 @@ struct Resolver<'a: 'b, 'b> {
} }
impl<'a, 'b> Resolver<'a, 'b> { impl<'a, 'b> Resolver<'a, 'b> {
fn resolve(&mut self, recipe: &Recipe<'a>) -> Result<(), Error<'a>> { fn resolve(&mut self, recipe: &Recipe<'a>) -> Result<(), CompileError<'a>> {
if self.resolved.contains(recipe.name) { if self.resolved.contains(recipe.name) {
return Ok(()) return Ok(())
} }
@ -519,7 +519,7 @@ impl<'a, 'b> Resolver<'a, 'b> {
fn resolve_assignments<'a>( fn resolve_assignments<'a>(
assignments: &Map<&'a str, Expression<'a>>, assignments: &Map<&'a str, Expression<'a>>,
assignment_tokens: &Map<&'a str, Token<'a>>, assignment_tokens: &Map<&'a str, Token<'a>>,
) -> Result<(), Error<'a>> { ) -> Result<(), CompileError<'a>> {
let mut resolver = AssignmentResolver { let mut resolver = AssignmentResolver {
assignments: assignments, assignments: assignments,
@ -545,7 +545,7 @@ struct AssignmentResolver<'a: 'b, 'b> {
} }
impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> { impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
fn resolve_assignment(&mut self, name: &'a str) -> Result<(), Error<'a>> { fn resolve_assignment(&mut self, name: &'a str) -> Result<(), CompileError<'a>> {
if self.evaluated.contains(name) { if self.evaluated.contains(name) {
return Ok(()); return Ok(());
} }
@ -562,7 +562,7 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
Ok(()) Ok(())
} }
fn resolve_expression(&mut self, expression: &Expression<'a>) -> Result<(), Error<'a>> { fn resolve_expression(&mut self, expression: &Expression<'a>) -> Result<(), CompileError<'a>> {
match *expression { match *expression {
Expression::Variable{name, ref token} => { Expression::Variable{name, ref token} => {
if self.evaluated.contains(name) { if self.evaluated.contains(name) {
@ -695,7 +695,7 @@ impl<'a, 'b> Evaluator<'a, 'b> {
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
struct Error<'a> { struct CompileError<'a> {
text: &'a str, text: &'a str,
index: usize, index: usize,
line: usize, line: usize,
@ -728,8 +728,8 @@ enum ErrorKind<'a> {
UnterminatedString, UnterminatedString,
} }
fn internal_error(message: String) -> Error<'static> { fn internal_error(message: String) -> CompileError<'static> {
Error { CompileError {
text: "", text: "",
index: 0, index: 0,
line: 0, line: 0,
@ -773,7 +773,7 @@ struct CookedString<'a> {
cooked: String, cooked: String,
} }
fn cook_string<'a>(token: &Token<'a>) -> Result<CookedString<'a>, Error<'a>> { fn cook_string<'a>(token: &Token<'a>) -> Result<CookedString<'a>, CompileError<'a>> {
let raw = &token.lexeme[1..token.lexeme.len()-1]; let raw = &token.lexeme[1..token.lexeme.len()-1];
if let RawString = token.kind { if let RawString = token.kind {
@ -929,15 +929,16 @@ fn maybe_bold(colors: bool) -> ansi_term::Style {
} }
} }
impl<'a> Display for Error<'a> { impl<'a> Display for CompileError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use ErrorKind::*;
let red = maybe_red(f.alternate()); let red = maybe_red(f.alternate());
let bold = maybe_bold(f.alternate()); let bold = maybe_bold(f.alternate());
write!(f, "{} {}", red.paint("error:"), bold.prefix())?; write!(f, "{} {}", red.paint("error:"), bold.prefix())?;
match self.kind { match self.kind {
ErrorKind::CircularRecipeDependency{recipe, ref circle} => { CircularRecipeDependency{recipe, ref circle} => {
if circle.len() == 2 { if circle.len() == 2 {
write!(f, "recipe `{}` depends on itself", recipe)?; write!(f, "recipe `{}` depends on itself", recipe)?;
} else { } else {
@ -945,7 +946,7 @@ impl<'a> Display for Error<'a> {
recipe, circle.join(" -> "))?; recipe, circle.join(" -> "))?;
} }
} }
ErrorKind::CircularVariableDependency{variable, ref circle} => { CircularVariableDependency{variable, ref circle} => {
if circle.len() == 2 { if circle.len() == 2 {
writeln!(f, "variable `{}` depends on its own value: `{}`", writeln!(f, "variable `{}` depends on its own value: `{}`",
variable, circle.join(" -> "))?; variable, circle.join(" -> "))?;
@ -954,68 +955,68 @@ impl<'a> Display for Error<'a> {
variable, circle.join(" -> "))?; variable, circle.join(" -> "))?;
} }
} }
ErrorKind::InvalidEscapeSequence{character} => { InvalidEscapeSequence{character} => {
writeln!(f, "`\\{}` is not a valid escape sequence", writeln!(f, "`\\{}` is not a valid escape sequence",
character.escape_default().collect::<String>())?; character.escape_default().collect::<String>())?;
} }
ErrorKind::DuplicateParameter{recipe, parameter} => { DuplicateParameter{recipe, parameter} => {
writeln!(f, "recipe `{}` has duplicate parameter `{}`", recipe, parameter)?; writeln!(f, "recipe `{}` has duplicate parameter `{}`", recipe, parameter)?;
} }
ErrorKind::DuplicateVariable{variable} => { DuplicateVariable{variable} => {
writeln!(f, "variable `{}` is has multiple definitions", variable)?; writeln!(f, "variable `{}` is has multiple definitions", variable)?;
} }
ErrorKind::UnexpectedToken{ref expected, found} => { UnexpectedToken{ref expected, found} => {
writeln!(f, "expected {} but found {}", Or(expected), found)?; writeln!(f, "expected {} but found {}", Or(expected), found)?;
} }
ErrorKind::DuplicateDependency{recipe, dependency} => { DuplicateDependency{recipe, dependency} => {
writeln!(f, "recipe `{}` has duplicate dependency `{}`", recipe, dependency)?; writeln!(f, "recipe `{}` has duplicate dependency `{}`", recipe, dependency)?;
} }
ErrorKind::DuplicateRecipe{recipe, first} => { DuplicateRecipe{recipe, first} => {
writeln!(f, "recipe `{}` first defined on line {} is redefined on line {}", writeln!(f, "recipe `{}` first defined on line {} is redefined on line {}",
recipe, first, self.line)?; recipe, first, self.line)?;
} }
ErrorKind::DependencyHasParameters{recipe, dependency} => { DependencyHasParameters{recipe, dependency} => {
writeln!(f, "recipe `{}` depends on `{}` which requires arguments. \ writeln!(f, "recipe `{}` depends on `{}` which requires arguments. \
dependencies may not require arguments", recipe, dependency)?; dependencies may not require arguments", recipe, dependency)?;
} }
ErrorKind::ParameterShadowsVariable{parameter} => { ParameterShadowsVariable{parameter} => {
writeln!(f, "parameter `{}` shadows variable of the same name", parameter)?; writeln!(f, "parameter `{}` shadows variable of the same name", parameter)?;
} }
ErrorKind::RequiredParameterFollowsDefaultParameter{parameter} => { RequiredParameterFollowsDefaultParameter{parameter} => {
writeln!(f, "non-default parameter `{}` follows default parameter", parameter)?; writeln!(f, "non-default parameter `{}` follows default parameter", parameter)?;
} }
ErrorKind::MixedLeadingWhitespace{whitespace} => { MixedLeadingWhitespace{whitespace} => {
writeln!(f, writeln!(f,
"found a mix of tabs and spaces in leading whitespace: `{}`\n\ "found a mix of tabs and spaces in leading whitespace: `{}`\n\
leading whitespace may consist of tabs or spaces, but not both", leading whitespace may consist of tabs or spaces, but not both",
show_whitespace(whitespace) show_whitespace(whitespace)
)?; )?;
} }
ErrorKind::ExtraLeadingWhitespace => { ExtraLeadingWhitespace => {
writeln!(f, "recipe line has extra leading whitespace")?; writeln!(f, "recipe line has extra leading whitespace")?;
} }
ErrorKind::InconsistentLeadingWhitespace{expected, found} => { InconsistentLeadingWhitespace{expected, found} => {
writeln!(f, writeln!(f,
"inconsistant leading whitespace: recipe started with `{}` but found line with `{}`:", "inconsistant leading whitespace: recipe started with `{}` but found line with `{}`:",
show_whitespace(expected), show_whitespace(found) show_whitespace(expected), show_whitespace(found)
)?; )?;
} }
ErrorKind::OuterShebang => { OuterShebang => {
writeln!(f, "a shebang `#!` is reserved syntax outside of recipes")?; writeln!(f, "a shebang `#!` is reserved syntax outside of recipes")?;
} }
ErrorKind::UnknownDependency{recipe, unknown} => { UnknownDependency{recipe, unknown} => {
writeln!(f, "recipe `{}` has unknown dependency `{}`", recipe, unknown)?; writeln!(f, "recipe `{}` has unknown dependency `{}`", recipe, unknown)?;
} }
ErrorKind::UndefinedVariable{variable} => { UndefinedVariable{variable} => {
writeln!(f, "variable `{}` not defined", variable)?; writeln!(f, "variable `{}` not defined", variable)?;
} }
ErrorKind::UnknownStartOfToken => { UnknownStartOfToken => {
writeln!(f, "unknown start of token:")?; writeln!(f, "unknown start of token:")?;
} }
ErrorKind::UnterminatedString => { UnterminatedString => {
writeln!(f, "unterminated string")?; writeln!(f, "unterminated string")?;
} }
ErrorKind::InternalError{ref message} => { InternalError{ref message} => {
writeln!(f, "internal error, this may indicate a bug in just: {}\n\ writeln!(f, "internal error, this may indicate a bug in just: {}\n\
consider filing an issue: https://github.com/casey/just/issues/new", consider filing an issue: https://github.com/casey/just/issues/new",
message)?; message)?;
@ -1213,6 +1214,7 @@ enum RunError<'a> {
impl<'a> Display for RunError<'a> { impl<'a> Display for RunError<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use RunError::*;
let red = maybe_red(f.alternate()); let red = maybe_red(f.alternate());
let bold = maybe_bold(f.alternate()); let bold = maybe_bold(f.alternate());
write!(f, "{} {}", red.paint("error:"), bold.prefix())?; write!(f, "{} {}", red.paint("error:"), bold.prefix())?;
@ -1220,23 +1222,23 @@ impl<'a> Display for RunError<'a> {
let mut error_token = None; let mut error_token = None;
match *self { match *self {
RunError::UnknownRecipes{ref recipes, ref suggestion} => { UnknownRecipes{ref recipes, ref suggestion} => {
write!(f, "Justfile does not contain recipe{} {}.", write!(f, "Justfile does not contain recipe{} {}.",
maybe_s(recipes.len()), Or(&ticks(&recipes)))?; maybe_s(recipes.len()), Or(&ticks(&recipes)))?;
if let Some(suggestion) = *suggestion { if let Some(suggestion) = *suggestion {
write!(f, "\nDid you mean `{}`?", suggestion)?; write!(f, "\nDid you mean `{}`?", suggestion)?;
} }
}, },
RunError::UnknownOverrides{ref overrides} => { UnknownOverrides{ref overrides} => {
write!(f, "Variable{} {} overridden on the command line but not present in justfile", write!(f, "Variable{} {} overridden on the command line but not present in justfile",
maybe_s(overrides.len()), maybe_s(overrides.len()),
And(&overrides.iter().map(Tick).collect::<Vec<_>>()))?; And(&overrides.iter().map(Tick).collect::<Vec<_>>()))?;
}, },
RunError::NonLeadingRecipeWithParameters{recipe} => { NonLeadingRecipeWithParameters{recipe} => {
write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe \ write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe \
specified on the command line", recipe)?; specified on the command line", recipe)?;
}, },
RunError::ArgumentCountMismatch{recipe, found, min, max} => { ArgumentCountMismatch{recipe, found, min, max} => {
if min == max { if min == max {
let expected = min; let expected = min;
write!(f, "Recipe `{}` got {} argument{} but {}takes {}", write!(f, "Recipe `{}` got {} argument{} but {}takes {}",
@ -1250,16 +1252,16 @@ impl<'a> Display for RunError<'a> {
recipe, found, maybe_s(found), max)?; recipe, found, maybe_s(found), max)?;
} }
}, },
RunError::Code{recipe, code} => { Code{recipe, code} => {
write!(f, "Recipe `{}` failed with exit code {}", recipe, code)?; write!(f, "Recipe `{}` failed with exit code {}", recipe, code)?;
}, },
RunError::Signal{recipe, signal} => { Signal{recipe, signal} => {
write!(f, "Recipe `{}` wast terminated by signal {}", recipe, signal)?; write!(f, "Recipe `{}` wast terminated by signal {}", recipe, signal)?;
} }
RunError::UnknownFailure{recipe} => { UnknownFailure{recipe} => {
write!(f, "Recipe `{}` failed for an unknown reason", recipe)?; write!(f, "Recipe `{}` failed for an unknown reason", recipe)?;
}, },
RunError::IoError{recipe, ref io_error} => { IoError{recipe, ref io_error} => {
match io_error.kind() { match io_error.kind() {
io::ErrorKind::NotFound => write!(f, io::ErrorKind::NotFound => write!(f,
"Recipe `{}` could not be run because just could not find `sh` the command:\n{}", "Recipe `{}` could not be run because just could not find `sh` the command:\n{}",
@ -1271,23 +1273,23 @@ impl<'a> Display for RunError<'a> {
launching `sh`:\n{}", recipe, io_error), launching `sh`:\n{}", recipe, io_error),
}?; }?;
}, },
RunError::TmpdirIoError{recipe, ref io_error} => TmpdirIoError{recipe, ref io_error} =>
write!(f, "Recipe `{}` could not be run because of an IO error while trying \ write!(f, "Recipe `{}` could not be run because of an IO error while trying \
to create a temporary directory or write a file to that directory`:\n{}", to create a temporary directory or write a file to that directory`:\n{}",
recipe, io_error)?, recipe, io_error)?,
RunError::BacktickCode{code, ref token} => { BacktickCode{code, ref token} => {
write!(f, "backtick failed with exit code {}\n", code)?; write!(f, "backtick failed with exit code {}\n", code)?;
error_token = Some(token); error_token = Some(token);
} }
RunError::BacktickSignal{ref token, signal} => { BacktickSignal{ref token, signal} => {
write!(f, "backtick was terminated by signal {}", signal)?; write!(f, "backtick was terminated by signal {}", signal)?;
error_token = Some(token); error_token = Some(token);
} }
RunError::BacktickUnknownFailure{ref token} => { BacktickUnknownFailure{ref token} => {
write!(f, "backtick failed for an uknown reason")?; write!(f, "backtick failed for an uknown reason")?;
error_token = Some(token); error_token = Some(token);
} }
RunError::BacktickIoError{ref token, ref io_error} => { BacktickIoError{ref token, ref io_error} => {
match io_error.kind() { match io_error.kind() {
io::ErrorKind::NotFound => write!( io::ErrorKind::NotFound => write!(
f, "backtick could not be run because just could not find `sh` the command:\n{}", f, "backtick could not be run because just could not find `sh` the command:\n{}",
@ -1299,11 +1301,11 @@ impl<'a> Display for RunError<'a> {
}?; }?;
error_token = Some(token); error_token = Some(token);
} }
RunError::BacktickUtf8Error{ref token, ref utf8_error} => { BacktickUtf8Error{ref token, ref utf8_error} => {
write!(f, "backtick succeeded but stdout was not utf8: {}", utf8_error)?; write!(f, "backtick succeeded but stdout was not utf8: {}", utf8_error)?;
error_token = Some(token); error_token = Some(token);
} }
RunError::InternalError{ref message} => { InternalError{ref message} => {
write!(f, "internal error, this may indicate a bug in just: {} \ write!(f, "internal error, this may indicate a bug in just: {} \
consider filing an issue: https://github.com/casey/just/issues/new", consider filing an issue: https://github.com/casey/just/issues/new",
message)?; message)?;
@ -1332,8 +1334,8 @@ struct Token<'a> {
} }
impl<'a> Token<'a> { impl<'a> Token<'a> {
fn error(&self, kind: ErrorKind<'a>) -> Error<'a> { fn error(&self, kind: ErrorKind<'a>) -> CompileError<'a> {
Error { CompileError {
text: self.text, text: self.text,
index: self.index + self.prefix.len(), index: self.index + self.prefix.len(),
line: self.line, line: self.line,
@ -1397,7 +1399,7 @@ fn token(pattern: &str) -> Regex {
re(&s) re(&s)
} }
fn tokenize(text: &str) -> Result<Vec<Token>, Error> { fn tokenize(text: &str) -> Result<Vec<Token>, CompileError> {
lazy_static! { lazy_static! {
static ref BACKTICK: Regex = token(r"`[^`\n\r]*`" ); static ref BACKTICK: Regex = token(r"`[^`\n\r]*`" );
static ref COLON: Regex = token(r":" ); static ref COLON: Regex = token(r":" );
@ -1439,7 +1441,7 @@ fn tokenize(text: &str) -> Result<Vec<Token>, Error> {
macro_rules! error { macro_rules! error {
($kind:expr) => {{ ($kind:expr) => {{
Err(Error { Err(CompileError {
text: text, text: text,
index: index, index: index,
line: line, line: line,
@ -1644,7 +1646,7 @@ fn tokenize(text: &str) -> Result<Vec<Token>, Error> {
Ok(tokens) Ok(tokens)
} }
fn parse(text: &str) -> Result<Justfile, Error> { fn parse(text: &str) -> Result<Justfile, CompileError> {
let tokens = tokenize(text)?; let tokens = tokenize(text)?;
let filtered: Vec<_> = tokens.into_iter().filter(|token| token.kind != Comment).collect(); let filtered: Vec<_> = tokens.into_iter().filter(|token| token.kind != Comment).collect();
let parser = Parser { let parser = Parser {
@ -1716,14 +1718,14 @@ impl<'a> Parser<'a> {
} }
} }
fn unexpected_token(&self, found: &Token<'a>, expected: &[TokenKind]) -> Error<'a> { fn unexpected_token(&self, found: &Token<'a>, expected: &[TokenKind]) -> CompileError<'a> {
found.error(ErrorKind::UnexpectedToken { found.error(ErrorKind::UnexpectedToken {
expected: expected.to_vec(), expected: expected.to_vec(),
found: found.kind, found: found.kind,
}) })
} }
fn recipe(&mut self, name: Token<'a>) -> Result<(), Error<'a>> { fn recipe(&mut self, name: Token<'a>) -> Result<(), CompileError<'a>> {
if let Some(recipe) = self.recipes.get(name.lexeme) { if let Some(recipe) = self.recipes.get(name.lexeme) {
return Err(name.error(ErrorKind::DuplicateRecipe { return Err(name.error(ErrorKind::DuplicateRecipe {
recipe: recipe.name, recipe: recipe.name,
@ -1851,7 +1853,7 @@ impl<'a> Parser<'a> {
Ok(()) Ok(())
} }
fn expression(&mut self, interpolation: bool) -> Result<Expression<'a>, Error<'a>> { fn expression(&mut self, interpolation: bool) -> Result<Expression<'a>, CompileError<'a>> {
let first = self.tokens.next().unwrap(); let first = self.tokens.next().unwrap();
let lhs = match first.kind { let lhs = match first.kind {
Name => Expression::Variable {name: first.lexeme, token: first}, Name => Expression::Variable {name: first.lexeme, token: first},
@ -1881,7 +1883,7 @@ impl<'a> Parser<'a> {
} }
} }
fn assignment(&mut self, name: Token<'a>, export: bool) -> Result<(), Error<'a>> { fn assignment(&mut self, name: Token<'a>, export: bool) -> Result<(), CompileError<'a>> {
if self.assignments.contains_key(name.lexeme) { if self.assignments.contains_key(name.lexeme) {
return Err(name.error(ErrorKind::DuplicateVariable {variable: name.lexeme})); return Err(name.error(ErrorKind::DuplicateVariable {variable: name.lexeme}));
} }
@ -1894,7 +1896,7 @@ impl<'a> Parser<'a> {
Ok(()) Ok(())
} }
fn file(mut self) -> Result<Justfile<'a>, Error<'a>> { fn file(mut self) -> Result<Justfile<'a>, CompileError<'a>> {
loop { loop {
match self.tokens.next() { match self.tokens.next() {
Some(token) => match token.kind { Some(token) => match token.kind {
@ -1918,7 +1920,7 @@ impl<'a> Parser<'a> {
})), })),
_ => return return Err(self.unexpected_token(&token, &[Name])), _ => return return Err(self.unexpected_token(&token, &[Name])),
}, },
None => return Err(Error { None => return Err(CompileError {
text: self.text, text: self.text,
index: 0, index: 0,
line: 0, line: 0,

View File

@ -1,7 +1,7 @@
extern crate tempdir; extern crate tempdir;
extern crate brev; extern crate brev;
use super::{Token, Error, ErrorKind, Justfile, RunError, RunOptions}; use super::{Token, CompileError, ErrorKind, Justfile, RunError, RunOptions};
use super::TokenKind::*; use super::TokenKind::*;
fn tokenize_success(text: &str, expected_summary: &str) { fn tokenize_success(text: &str, expected_summary: &str) {
@ -19,7 +19,7 @@ fn tokenize_success(text: &str, expected_summary: &str) {
assert_eq!(text, roundtrip); assert_eq!(text, roundtrip);
} }
fn tokenize_error(text: &str, expected: Error) { fn tokenize_error(text: &str, expected: CompileError) {
if let Err(error) = super::tokenize(text) { if let Err(error) = super::tokenize(text) {
assert_eq!(error.text, expected.text); assert_eq!(error.text, expected.text);
assert_eq!(error.index, expected.index); assert_eq!(error.index, expected.index);
@ -72,7 +72,7 @@ fn parse_summary(input: &str, output: &str) {
} }
} }
fn parse_error(text: &str, expected: Error) { fn parse_error(text: &str, expected: CompileError) {
if let Err(error) = super::parse(text) { if let Err(error) = super::parse(text) {
assert_eq!(error.text, expected.text); assert_eq!(error.text, expected.text);
assert_eq!(error.index, expected.index); assert_eq!(error.index, expected.index);
@ -192,7 +192,7 @@ fn tokenize_space_then_tab() {
1 1
\t2 \t2
"; ";
tokenize_error(text, Error { tokenize_error(text, CompileError {
text: text, text: text,
index: 9, index: 9,
line: 3, line: 3,
@ -209,7 +209,7 @@ fn tokenize_tabs_then_tab_space() {
\t\t 1 \t\t 1
\t 2 \t 2
"; ";
tokenize_error(text, Error { tokenize_error(text, CompileError {
text: text, text: text,
index: 12, index: 12,
line: 3, line: 3,
@ -222,7 +222,7 @@ fn tokenize_tabs_then_tab_space() {
#[test] #[test]
fn tokenize_outer_shebang() { fn tokenize_outer_shebang() {
let text = "#!/usr/bin/env bash"; let text = "#!/usr/bin/env bash";
tokenize_error(text, Error { tokenize_error(text, CompileError {
text: text, text: text,
index: 0, index: 0,
line: 0, line: 0,
@ -235,7 +235,7 @@ fn tokenize_outer_shebang() {
#[test] #[test]
fn tokenize_unknown() { fn tokenize_unknown() {
let text = "~"; let text = "~";
tokenize_error(text, Error { tokenize_error(text, CompileError {
text: text, text: text,
index: 0, index: 0,
line: 0, line: 0,
@ -382,7 +382,7 @@ r#"a:
#[test] #[test]
fn missing_colon() { fn missing_colon() {
let text = "a b c\nd e f"; let text = "a b c\nd e f";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 5, index: 5,
line: 0, line: 0,
@ -395,7 +395,7 @@ fn missing_colon() {
#[test] #[test]
fn missing_default_eol() { fn missing_default_eol() {
let text = "hello arg=\n"; let text = "hello arg=\n";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 10, index: 10,
line: 0, line: 0,
@ -408,7 +408,7 @@ fn missing_default_eol() {
#[test] #[test]
fn missing_default_eof() { fn missing_default_eof() {
let text = "hello arg="; let text = "hello arg=";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 10, index: 10,
line: 0, line: 0,
@ -421,7 +421,7 @@ fn missing_default_eof() {
#[test] #[test]
fn missing_default_colon() { fn missing_default_colon() {
let text = "hello arg=:"; let text = "hello arg=:";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 10, index: 10,
line: 0, line: 0,
@ -434,7 +434,7 @@ fn missing_default_colon() {
#[test] #[test]
fn missing_default_backtick() { fn missing_default_backtick() {
let text = "hello arg=`hello`"; let text = "hello arg=`hello`";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 10, index: 10,
line: 0, line: 0,
@ -447,7 +447,7 @@ fn missing_default_backtick() {
#[test] #[test]
fn required_after_default() { fn required_after_default() {
let text = "hello arg='foo' bar:"; let text = "hello arg='foo' bar:";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 16, index: 16,
line: 0, line: 0,
@ -460,7 +460,7 @@ fn required_after_default() {
#[test] #[test]
fn missing_eol() { fn missing_eol() {
let text = "a b c: z ="; let text = "a b c: z =";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 9, index: 9,
line: 0, line: 0,
@ -478,7 +478,7 @@ fn eof_test() {
#[test] #[test]
fn duplicate_parameter() { fn duplicate_parameter() {
let text = "a b b:"; let text = "a b b:";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 4, index: 4,
line: 0, line: 0,
@ -491,7 +491,7 @@ fn duplicate_parameter() {
#[test] #[test]
fn parameter_shadows_varible() { fn parameter_shadows_varible() {
let text = "foo = \"h\"\na foo:"; let text = "foo = \"h\"\na foo:";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 12, index: 12,
line: 1, line: 1,
@ -504,7 +504,7 @@ fn parameter_shadows_varible() {
#[test] #[test]
fn dependency_has_parameters() { fn dependency_has_parameters() {
let text = "foo arg:\nb: foo"; let text = "foo arg:\nb: foo";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 12, index: 12,
line: 1, line: 1,
@ -517,7 +517,7 @@ fn dependency_has_parameters() {
#[test] #[test]
fn duplicate_dependency() { fn duplicate_dependency() {
let text = "a b c: b c z z"; let text = "a b c: b c z z";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 13, index: 13,
line: 0, line: 0,
@ -530,7 +530,7 @@ fn duplicate_dependency() {
#[test] #[test]
fn duplicate_recipe() { fn duplicate_recipe() {
let text = "a:\nb:\na:"; let text = "a:\nb:\na:";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 6, index: 6,
line: 2, line: 2,
@ -543,7 +543,7 @@ fn duplicate_recipe() {
#[test] #[test]
fn circular_recipe_dependency() { fn circular_recipe_dependency() {
let text = "a: b\nb: a"; let text = "a: b\nb: a";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 8, index: 8,
line: 1, line: 1,
@ -556,7 +556,7 @@ fn circular_recipe_dependency() {
#[test] #[test]
fn circular_variable_dependency() { fn circular_variable_dependency() {
let text = "a = b\nb = a"; let text = "a = b\nb = a";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 0, index: 0,
line: 0, line: 0,
@ -569,7 +569,7 @@ fn circular_variable_dependency() {
#[test] #[test]
fn duplicate_variable() { fn duplicate_variable() {
let text = "a = \"0\"\na = \"0\""; let text = "a = \"0\"\na = \"0\"";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 8, index: 8,
line: 1, line: 1,
@ -582,7 +582,7 @@ fn duplicate_variable() {
#[test] #[test]
fn unterminated_string() { fn unterminated_string() {
let text = r#"a = ""#; let text = r#"a = ""#;
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 3, index: 3,
line: 0, line: 0,
@ -595,7 +595,7 @@ fn unterminated_string() {
#[test] #[test]
fn unterminated_string_with_escapes() { fn unterminated_string_with_escapes() {
let text = r#"a = "\n\t\r\"\\"#; let text = r#"a = "\n\t\r\"\\"#;
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 3, index: 3,
line: 0, line: 0,
@ -634,7 +634,7 @@ fn parameters() {
#[test] #[test]
fn self_recipe_dependency() { fn self_recipe_dependency() {
let text = "a: a"; let text = "a: a";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 3, index: 3,
line: 0, line: 0,
@ -647,7 +647,7 @@ fn self_recipe_dependency() {
#[test] #[test]
fn self_variable_dependency() { fn self_variable_dependency() {
let text = "a = a"; let text = "a = a";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 0, index: 0,
line: 0, line: 0,
@ -660,7 +660,7 @@ fn self_variable_dependency() {
#[test] #[test]
fn unknown_dependency() { fn unknown_dependency() {
let text = "a: b"; let text = "a: b";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 3, index: 3,
line: 0, line: 0,
@ -673,7 +673,7 @@ fn unknown_dependency() {
#[test] #[test]
fn mixed_leading_whitespace() { fn mixed_leading_whitespace() {
let text = "a:\n\t echo hello"; let text = "a:\n\t echo hello";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 3, index: 3,
line: 1, line: 1,
@ -724,7 +724,7 @@ fn extra_whitespace() {
// we might want to make extra leading whitespace a line continuation in the future, // we might want to make extra leading whitespace a line continuation in the future,
// so make it a error for now // so make it a error for now
let text = "a:\n blah\n blarg"; let text = "a:\n blah\n blarg";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 10, index: 10,
line: 2, line: 2,
@ -740,7 +740,7 @@ fn extra_whitespace() {
#[test] #[test]
fn interpolation_outside_of_recipe() { fn interpolation_outside_of_recipe() {
let text = "{{"; let text = "{{";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 0, index: 0,
line: 0, line: 0,
@ -753,7 +753,7 @@ fn interpolation_outside_of_recipe() {
#[test] #[test]
fn unclosed_interpolation_delimiter() { fn unclosed_interpolation_delimiter() {
let text = "a:\n echo {{ foo"; let text = "a:\n echo {{ foo";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 15, index: 15,
line: 1, line: 1,
@ -766,7 +766,7 @@ fn unclosed_interpolation_delimiter() {
#[test] #[test]
fn unknown_expression_variable() { fn unknown_expression_variable() {
let text = "x = yy"; let text = "x = yy";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 4, index: 4,
line: 0, line: 0,
@ -779,7 +779,7 @@ fn unknown_expression_variable() {
#[test] #[test]
fn unknown_interpolation_variable() { fn unknown_interpolation_variable() {
let text = "x:\n {{ hello}}"; let text = "x:\n {{ hello}}";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 9, index: 9,
line: 1, line: 1,
@ -792,7 +792,7 @@ fn unknown_interpolation_variable() {
#[test] #[test]
fn unknown_second_interpolation_variable() { fn unknown_second_interpolation_variable() {
let text = "wtf=\"x\"\nx:\n echo\n foo {{wtf}} {{ lol }}"; let text = "wtf=\"x\"\nx:\n echo\n foo {{wtf}} {{ lol }}";
parse_error(text, Error { parse_error(text, CompileError {
text: text, text: text,
index: 33, index: 33,
line: 3, line: 3,