Add file paths to error messages (#1737)
This commit is contained in:
parent
f745316e88
commit
7337447d42
@ -42,6 +42,7 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
||||
column: 0,
|
||||
length: 0,
|
||||
kind: TokenKind::Unspecified,
|
||||
path: "".as_ref(),
|
||||
};
|
||||
return Err(CompileError::new(token, Internal { message }));
|
||||
}
|
||||
|
@ -60,6 +60,10 @@ impl Color {
|
||||
self.redirect(Stream::Stdout)
|
||||
}
|
||||
|
||||
pub(crate) fn context(self) -> Self {
|
||||
self.restyle(Style::new().fg(Blue).bold())
|
||||
}
|
||||
|
||||
pub(crate) fn doc(self) -> Self {
|
||||
self.restyle(Style::new().fg(Blue))
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ impl Compiler {
|
||||
paths.push(root.into());
|
||||
|
||||
while let Some(current) = paths.pop() {
|
||||
let src = loader.load(¤t)?;
|
||||
let tokens = Lexer::lex(src)?;
|
||||
let (relative, src) = loader.load(root, ¤t)?;
|
||||
let tokens = Lexer::lex(relative, src)?;
|
||||
let mut ast = Parser::parse(&tokens)?;
|
||||
|
||||
srcs.insert(current.clone(), src);
|
||||
@ -56,9 +56,9 @@ impl Compiler {
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_compile(src: &str) -> CompileResult<Justfile> {
|
||||
let tokens = Lexer::lex(src)?;
|
||||
let tokens = Lexer::test_lex(src)?;
|
||||
let ast = Parser::parse(&tokens)?;
|
||||
let root = PathBuf::from("<ROOT>");
|
||||
let root = PathBuf::from("justfile");
|
||||
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
||||
asts.insert(root.clone(), ast);
|
||||
Analyzer::analyze(&asts, &root)
|
||||
|
68
src/lexer.rs
68
src/lexer.rs
@ -9,38 +9,45 @@ use {super::*, CompileErrorKind::*, TokenKind::*};
|
||||
/// slight against regular expressions, the lexer was just idiosyncratically
|
||||
/// bad.
|
||||
pub(crate) struct Lexer<'src> {
|
||||
/// Source text
|
||||
src: &'src str,
|
||||
/// Char iterator
|
||||
chars: Chars<'src>,
|
||||
/// Tokens
|
||||
tokens: Vec<Token<'src>>,
|
||||
/// Current token start
|
||||
token_start: Position,
|
||||
/// Current token end
|
||||
token_end: Position,
|
||||
/// Next character to be lexed
|
||||
next: Option<char>,
|
||||
/// Next indent will start a recipe body
|
||||
recipe_body_pending: bool,
|
||||
/// Inside recipe body
|
||||
recipe_body: bool,
|
||||
/// Indentation stack
|
||||
indentation: Vec<&'src str>,
|
||||
/// Interpolation token start stack
|
||||
interpolation_stack: Vec<Token<'src>>,
|
||||
/// Next character to be lexed
|
||||
next: Option<char>,
|
||||
/// Current open delimiters
|
||||
open_delimiters: Vec<(Delimiter, usize)>,
|
||||
/// Path to source file
|
||||
path: &'src Path,
|
||||
/// Inside recipe body
|
||||
recipe_body: bool,
|
||||
/// Next indent will start a recipe body
|
||||
recipe_body_pending: bool,
|
||||
/// Source text
|
||||
src: &'src str,
|
||||
/// Tokens
|
||||
tokens: Vec<Token<'src>>,
|
||||
/// Current token end
|
||||
token_end: Position,
|
||||
/// Current token start
|
||||
token_start: Position,
|
||||
}
|
||||
|
||||
impl<'src> Lexer<'src> {
|
||||
/// Lex `text`
|
||||
pub(crate) fn lex(src: &'src str) -> CompileResult<Vec<Token<'src>>> {
|
||||
Lexer::new(src).tokenize()
|
||||
/// Lex `src`
|
||||
pub(crate) fn lex(path: &'src Path, src: &'src str) -> CompileResult<'src, Vec<Token<'src>>> {
|
||||
Lexer::new(path, src).tokenize()
|
||||
}
|
||||
|
||||
/// Create a new Lexer to lex `text`
|
||||
fn new(src: &'src str) -> Lexer<'src> {
|
||||
#[cfg(test)]
|
||||
pub(crate) fn test_lex(src: &'src str) -> CompileResult<'src, Vec<Token<'src>>> {
|
||||
Lexer::new("justfile".as_ref(), src).tokenize()
|
||||
}
|
||||
|
||||
/// Create a new Lexer to lex `src`
|
||||
fn new(path: &'src Path, src: &'src str) -> Lexer<'src> {
|
||||
let mut chars = src.chars();
|
||||
let next = chars.next();
|
||||
|
||||
@ -62,6 +69,7 @@ impl<'src> Lexer<'src> {
|
||||
chars,
|
||||
next,
|
||||
src,
|
||||
path,
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,6 +197,7 @@ impl<'src> Lexer<'src> {
|
||||
src: self.src,
|
||||
length: self.token_end.offset - self.token_start.offset,
|
||||
kind,
|
||||
path: self.path,
|
||||
});
|
||||
|
||||
// Set `token_start` to point after the lexed token
|
||||
@ -205,6 +214,7 @@ impl<'src> Lexer<'src> {
|
||||
column: self.token_end.column,
|
||||
length: 0,
|
||||
kind: Unspecified,
|
||||
path: self.path,
|
||||
};
|
||||
CompileError::new(
|
||||
token,
|
||||
@ -240,6 +250,7 @@ impl<'src> Lexer<'src> {
|
||||
line: self.token_start.line,
|
||||
column: self.token_start.column,
|
||||
length,
|
||||
path: self.path,
|
||||
};
|
||||
|
||||
CompileError::new(token, kind)
|
||||
@ -920,7 +931,7 @@ mod tests {
|
||||
text.to_owned()
|
||||
};
|
||||
|
||||
let have = Lexer::lex(&text).unwrap();
|
||||
let have = Lexer::test_lex(&text).unwrap();
|
||||
|
||||
let have_kinds = have
|
||||
.iter()
|
||||
@ -1028,7 +1039,7 @@ mod tests {
|
||||
length: usize,
|
||||
kind: CompileErrorKind,
|
||||
) {
|
||||
match Lexer::lex(src) {
|
||||
match Lexer::test_lex(src) {
|
||||
Ok(_) => panic!("Lexing succeeded but expected"),
|
||||
Err(have) => {
|
||||
let want = CompileError {
|
||||
@ -1039,6 +1050,7 @@ mod tests {
|
||||
line,
|
||||
column,
|
||||
length,
|
||||
path: "justfile".as_ref(),
|
||||
},
|
||||
kind: Box::new(kind),
|
||||
};
|
||||
@ -2321,7 +2333,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn presume_error() {
|
||||
let compile_error = Lexer::new("!").presume('-').unwrap_err();
|
||||
let compile_error = Lexer::new("justfile".as_ref(), "!")
|
||||
.presume('-')
|
||||
.unwrap_err();
|
||||
assert_matches!(
|
||||
compile_error.token,
|
||||
Token {
|
||||
@ -2331,6 +2345,7 @@ mod tests {
|
||||
length: 0,
|
||||
src: "!",
|
||||
kind: Unspecified,
|
||||
path: _,
|
||||
}
|
||||
);
|
||||
assert_matches!(&*compile_error.kind,
|
||||
@ -2342,9 +2357,12 @@ mod tests {
|
||||
Error::Compile { compile_error }
|
||||
.color_display(Color::never())
|
||||
.to_string(),
|
||||
"error: Internal error, this may indicate a bug in just: \
|
||||
Lexer presumed character `-`\nconsider filing an issue: \
|
||||
https://github.com/casey/just/issues/new\n |\n1 | !\n | ^"
|
||||
"error: Internal error, this may indicate a bug in just: Lexer presumed character `-`
|
||||
consider filing an issue: https://github.com/casey/just/issues/new
|
||||
--> justfile:1:1
|
||||
|
|
||||
1 | !
|
||||
| ^"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,34 @@
|
||||
use super::*;
|
||||
|
||||
pub(crate) struct Loader {
|
||||
arena: Arena<String>,
|
||||
srcs: Arena<String>,
|
||||
paths: Arena<PathBuf>,
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
pub(crate) fn new() -> Self {
|
||||
Loader {
|
||||
arena: Arena::new(),
|
||||
srcs: Arena::new(),
|
||||
paths: Arena::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn load<'src>(&'src self, path: &Path) -> RunResult<&'src str> {
|
||||
pub(crate) fn load<'src>(
|
||||
&'src self,
|
||||
root: &Path,
|
||||
path: &Path,
|
||||
) -> RunResult<(&'src Path, &'src str)> {
|
||||
let src = fs::read_to_string(path).map_err(|io_error| Error::Load {
|
||||
path: path.to_owned(),
|
||||
io_error,
|
||||
})?;
|
||||
|
||||
Ok(self.arena.alloc(src))
|
||||
let relative = if let Ok(path) = path.strip_prefix(root.parent().unwrap()) {
|
||||
path
|
||||
} else {
|
||||
path
|
||||
};
|
||||
|
||||
Ok((self.paths.alloc(relative.into()), self.srcs.alloc(src)))
|
||||
}
|
||||
}
|
||||
|
15
src/name.rs
15
src/name.rs
@ -4,10 +4,11 @@ use super::*;
|
||||
/// it its own type for clarity.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub(crate) struct Name<'src> {
|
||||
pub(crate) offset: usize,
|
||||
pub(crate) column: usize,
|
||||
pub(crate) length: usize,
|
||||
pub(crate) line: usize,
|
||||
pub(crate) column: usize,
|
||||
pub(crate) offset: usize,
|
||||
pub(crate) path: &'src Path,
|
||||
pub(crate) src: &'src str,
|
||||
}
|
||||
|
||||
@ -20,11 +21,12 @@ impl<'src> Name<'src> {
|
||||
/// Turn this name back into a token
|
||||
pub(crate) fn token(&self) -> Token<'src> {
|
||||
Token {
|
||||
column: self.column,
|
||||
kind: TokenKind::Identifier,
|
||||
offset: self.offset,
|
||||
length: self.length,
|
||||
line: self.line,
|
||||
column: self.column,
|
||||
offset: self.offset,
|
||||
path: self.path,
|
||||
src: self.src,
|
||||
}
|
||||
}
|
||||
@ -32,10 +34,11 @@ impl<'src> Name<'src> {
|
||||
pub(crate) fn from_identifier(token: Token<'src>) -> Name {
|
||||
assert_eq!(token.kind, TokenKind::Identifier);
|
||||
Name {
|
||||
offset: token.offset,
|
||||
column: token.column,
|
||||
length: token.length,
|
||||
line: token.line,
|
||||
column: token.column,
|
||||
offset: token.offset,
|
||||
path: token.path,
|
||||
src: token.src,
|
||||
}
|
||||
}
|
||||
|
@ -927,7 +927,7 @@ mod tests {
|
||||
|
||||
fn test(text: &str, want: Tree) {
|
||||
let unindented = unindent(text);
|
||||
let tokens = Lexer::lex(&unindented).expect("lexing failed");
|
||||
let tokens = Lexer::test_lex(&unindented).expect("lexing failed");
|
||||
let justfile = Parser::parse(&tokens).expect("parsing failed");
|
||||
let have = justfile.tree();
|
||||
if have != want {
|
||||
@ -964,7 +964,7 @@ mod tests {
|
||||
length: usize,
|
||||
kind: CompileErrorKind,
|
||||
) {
|
||||
let tokens = Lexer::lex(src).expect("Lexing failed in parse test...");
|
||||
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
||||
|
||||
match Parser::parse(&tokens) {
|
||||
Ok(_) => panic!("Parsing unexpectedly succeeded"),
|
||||
@ -977,6 +977,7 @@ mod tests {
|
||||
line,
|
||||
column,
|
||||
length,
|
||||
path: "justfile".as_ref(),
|
||||
},
|
||||
kind: Box::new(kind),
|
||||
};
|
||||
|
@ -57,11 +57,11 @@ pub(crate) fn analysis_error(
|
||||
length: usize,
|
||||
kind: CompileErrorKind,
|
||||
) {
|
||||
let tokens = Lexer::lex(src).expect("Lexing failed in parse test...");
|
||||
let tokens = Lexer::test_lex(src).expect("Lexing failed in parse test...");
|
||||
|
||||
let ast = Parser::parse(&tokens).expect("Parsing failed in analysis test...");
|
||||
|
||||
let root = PathBuf::from("<ROOT>");
|
||||
let root = PathBuf::from("justfile");
|
||||
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
|
||||
asts.insert(root.clone(), ast);
|
||||
|
||||
@ -76,6 +76,7 @@ pub(crate) fn analysis_error(
|
||||
line,
|
||||
column,
|
||||
length,
|
||||
path: "justfile".as_ref(),
|
||||
},
|
||||
kind: Box::new(kind),
|
||||
};
|
||||
|
39
src/token.rs
39
src/token.rs
@ -2,12 +2,13 @@ use super::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub(crate) struct Token<'src> {
|
||||
pub(crate) offset: usize,
|
||||
pub(crate) column: usize,
|
||||
pub(crate) kind: TokenKind,
|
||||
pub(crate) length: usize,
|
||||
pub(crate) line: usize,
|
||||
pub(crate) column: usize,
|
||||
pub(crate) offset: usize,
|
||||
pub(crate) path: &'src Path,
|
||||
pub(crate) src: &'src str,
|
||||
pub(crate) kind: TokenKind,
|
||||
}
|
||||
|
||||
impl<'src> Token<'src> {
|
||||
@ -52,9 +53,35 @@ impl<'src> ColorDisplay for Token<'src> {
|
||||
i += c.len_utf8();
|
||||
}
|
||||
let line_number_width = line_number.to_string().len();
|
||||
writeln!(f, "{0:1$} |", "", line_number_width)?;
|
||||
writeln!(f, "{line_number} | {space_line}")?;
|
||||
write!(f, "{0:1$} |", "", line_number_width)?;
|
||||
writeln!(
|
||||
f,
|
||||
"{:width$}{} {}:{}:{}",
|
||||
"",
|
||||
color.context().paint("-->"),
|
||||
self.path.display(),
|
||||
line_number,
|
||||
self.column.ordinal(),
|
||||
width = line_number_width
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
"{:width$} {}",
|
||||
"",
|
||||
color.context().paint("|"),
|
||||
width = line_number_width
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
"{} {space_line}",
|
||||
color.context().paint(&format!("{line_number} |"))
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
"{:width$} {}",
|
||||
"",
|
||||
color.context().paint("|"),
|
||||
width = line_number_width
|
||||
)?;
|
||||
write!(
|
||||
f,
|
||||
" {0:1$}{2}{3:^<4$}{5}",
|
||||
|
@ -33,6 +33,7 @@ fn duplicate_attributes_are_disallowed() {
|
||||
.stderr(
|
||||
"
|
||||
error: Recipe attribute `no-exit-message` first used on line 1 is duplicated on line 2
|
||||
--> justfile:2:2
|
||||
|
|
||||
2 | [no-exit-message]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -72,6 +73,7 @@ fn multiple_attributes_one_line_error_message() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected ']' or ',', but found identifier
|
||||
--> justfile:1:17
|
||||
|
|
||||
1 | [macos, windows linux]
|
||||
| ^^^^^
|
||||
@ -95,6 +97,7 @@ fn multiple_attributes_one_line_duplicate_check() {
|
||||
.stderr(
|
||||
"
|
||||
error: Recipe attribute `linux` first used on line 1 is duplicated on line 2
|
||||
--> justfile:2:2
|
||||
|
|
||||
2 | [linux]
|
||||
| ^^^^^
|
||||
|
@ -27,6 +27,7 @@ fn non_leading_byte_order_mark_produces_error() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected \'@\', '!', \'[\', comment, end of file, end of line, or identifier, but found byte order mark
|
||||
--> justfile:3:1
|
||||
|
|
||||
3 | \u{feff}
|
||||
| ^
|
||||
@ -42,6 +43,7 @@ fn dont_mention_byte_order_mark_in_errors() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected '@', '!', '[', comment, end of file, end of line, or identifier, but found '{'
|
||||
--> justfile:1:1
|
||||
|
|
||||
1 | {
|
||||
| ^
|
||||
|
@ -61,6 +61,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:9
|
||||
|
|
||||
1 | a := if b == '' { '' } else { '' }
|
||||
| ^
|
||||
@ -79,6 +80,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:15
|
||||
|
|
||||
1 | a := if '' == b { '' } else { '' }
|
||||
| ^
|
||||
@ -97,6 +99,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:20
|
||||
|
|
||||
1 | a := if '' == '' { b } else { '' }
|
||||
| ^
|
||||
@ -115,6 +118,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:32
|
||||
|
|
||||
1 | a := if '' == '' { '' } else { b }
|
||||
| ^
|
||||
@ -133,6 +137,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Expected '!=', '==', '=~', '+', or '/', but found identifier
|
||||
--> justfile:1:12
|
||||
|
|
||||
1 | a := if '' a '' { '' } else { b }
|
||||
| ^
|
||||
@ -177,6 +182,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Expected keyword `else` but found `end of line`
|
||||
--> justfile:1:54
|
||||
|
|
||||
1 | TEST := if path_exists('/bin/bash') == 'true' {'yes'}
|
||||
| ^
|
||||
@ -192,6 +198,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Expected keyword `else` but found identifier `els`
|
||||
--> justfile:1:55
|
||||
|
|
||||
1 | TEST := if path_exists('/bin/bash') == 'true' {'yes'} els {'no'}
|
||||
| ^^^
|
||||
|
@ -5,6 +5,7 @@ test! {
|
||||
justfile: "(]",
|
||||
stderr: "
|
||||
error: Mismatched closing delimiter `]`. (Did you mean to close the `(` on line 1?)
|
||||
--> justfile:1:2
|
||||
|
|
||||
1 | (]
|
||||
| ^
|
||||
@ -17,6 +18,7 @@ test! {
|
||||
justfile: "]",
|
||||
stderr: "
|
||||
error: Unexpected closing delimiter `]`
|
||||
--> justfile:1:1
|
||||
|
|
||||
1 | ]
|
||||
| ^
|
||||
@ -96,6 +98,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Unterminated interpolation
|
||||
--> justfile:2:8
|
||||
|
|
||||
2 | echo {{ (
|
||||
| ^^
|
||||
|
@ -5,6 +5,7 @@ test! {
|
||||
justfile: "[private]\n[linux]\nalias t := test\n\ntest:\n",
|
||||
stderr: "
|
||||
error: Alias t has an invalid attribute `linux`
|
||||
--> justfile:3:7
|
||||
|
|
||||
3 | alias t := test
|
||||
| ^
|
||||
@ -17,6 +18,7 @@ test! {
|
||||
justfile: "foo := if '' == '' { '' } arlo { '' }",
|
||||
stderr: "
|
||||
error: Expected keyword `else` but found identifier `arlo`
|
||||
--> justfile:1:27
|
||||
|
|
||||
1 | foo := if '' == '' { '' } arlo { '' }
|
||||
| ^^^^
|
||||
@ -29,6 +31,7 @@ test! {
|
||||
justfile: "&~",
|
||||
stderr: "
|
||||
error: Expected character `&`
|
||||
--> justfile:1:2
|
||||
|
|
||||
1 | &~
|
||||
| ^
|
||||
@ -51,3 +54,61 @@ fn argument_count_mismatch() {
|
||||
.status(EXIT_FAILURE)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_path_is_indented_if_justfile_is_long() {
|
||||
Test::new()
|
||||
.justfile("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nfoo")
|
||||
.status(EXIT_FAILURE)
|
||||
.stderr(
|
||||
"
|
||||
error: Expected '*', ':', '$', identifier, or '+', but found end of file
|
||||
--> justfile:20:4
|
||||
|
|
||||
20 | foo
|
||||
| ^
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_paths_are_relative() {
|
||||
Test::new()
|
||||
.justfile("!include foo/bar.just")
|
||||
.write("foo/bar.just", "baz")
|
||||
.args(["--unstable"])
|
||||
.status(EXIT_FAILURE)
|
||||
.stderr(format!(
|
||||
"
|
||||
error: Expected '*', ':', '$', identifier, or '+', but found end of file
|
||||
--> foo{}bar.just:1:4
|
||||
|
|
||||
1 | baz
|
||||
| ^
|
||||
",
|
||||
MAIN_SEPARATOR
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_paths_not_in_subdir_are_absolute() {
|
||||
Test::new()
|
||||
.write("foo/justfile", "!include ../bar.just")
|
||||
.write("bar.just", "baz")
|
||||
.no_justfile()
|
||||
.args(["--unstable", "--justfile", "foo/justfile"])
|
||||
.status(EXIT_FAILURE)
|
||||
.stderr_regex(format!(
|
||||
"
|
||||
error: Expected '*', ':', '$', identifier, or '+', but found end of file
|
||||
--> {}.*{}bar.just:1:4
|
||||
|
|
||||
1 | baz
|
||||
| ^
|
||||
",
|
||||
MAIN_SEPARATOR, MAIN_SEPARATOR
|
||||
))
|
||||
.run();
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ fn print_error_from_parent_if_recipe_not_found_in_current() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `bar` not defined
|
||||
--> justfile:2:9
|
||||
|
|
||||
2 | echo {{bar}}
|
||||
| ^^^
|
||||
|
@ -85,9 +85,10 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `without_extension` failed:",
|
||||
"Could not extract parent from ``",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := without_extension(\'\')",
|
||||
" | ^^^^^^^^^^^^^^^^^").as_str(),
|
||||
@ -104,8 +105,9 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `extension` failed: Could not extract extension from ``",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := extension(\'\')",
|
||||
" | ^^^^^^^^^").as_str(),
|
||||
@ -122,8 +124,9 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `extension` failed: Could not extract extension from `foo`",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := extension(\'foo\')",
|
||||
" | ^^^^^^^^^").as_str(),
|
||||
@ -140,8 +143,9 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `file_stem` failed: Could not extract file stem from ``",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := file_stem(\'\')",
|
||||
" | ^^^^^^^^^").as_str(),
|
||||
@ -158,8 +162,9 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `file_name` failed: Could not extract file name from ``",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := file_name(\'\')",
|
||||
" | ^^^^^^^^^").as_str(),
|
||||
@ -176,9 +181,10 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `parent_directory` failed:",
|
||||
"Could not extract parent directory from ``",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := parent_directory(\'\')",
|
||||
" | ^^^^^^^^^^^^^^^^").as_str(),
|
||||
@ -195,9 +201,10 @@ foo:
|
||||
/bin/echo '{{we}}'
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n",
|
||||
stderr: format!("{} {}\n{}\n{}\n{}\n{}\n",
|
||||
"error: Call to function `parent_directory` failed:",
|
||||
"Could not extract parent directory from `/`",
|
||||
" --> justfile:1:8",
|
||||
" |",
|
||||
"1 | we := parent_directory(\'/\')",
|
||||
" | ^^^^^^^^^^^^^^^^").as_str(),
|
||||
@ -225,6 +232,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Call to function `env_var` failed: environment variable `ZADDY` not present
|
||||
--> justfile:2:10
|
||||
|
|
||||
2 | echo {{env_var('ZADDY')}}
|
||||
| ^^^^^^^
|
||||
@ -395,6 +403,7 @@ test! {
|
||||
foo\\
|
||||
^
|
||||
error: incomplete escape sequence, reached end of pattern prematurely
|
||||
--> justfile:2:11
|
||||
|
|
||||
2 | echo {{ replace_regex('barbarbar', 'foo\\', 'foo') }}
|
||||
| ^^^^^^^^^^^^^
|
||||
@ -498,6 +507,7 @@ fn join_argument_count_error() {
|
||||
.stderr(
|
||||
"
|
||||
error: Function `join` called with 1 argument but takes 2 or more
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | x := join(\'a\')
|
||||
| ^^^^
|
||||
@ -534,7 +544,15 @@ fn error_errors_with_message() {
|
||||
.justfile("x := error ('Thing Not Supported')")
|
||||
.args(["--evaluate"])
|
||||
.status(1)
|
||||
.stderr("error: Call to function `error` failed: Thing Not Supported\n |\n1 | x := error ('Thing Not Supported')\n | ^^^^^\n")
|
||||
.stderr(
|
||||
"
|
||||
error: Call to function `error` failed: Thing Not Supported
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | x := error ('Thing Not Supported')
|
||||
| ^^^^^
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ fn include_directive_with_no_path() {
|
||||
.stderr(
|
||||
"
|
||||
error: !include directive has no argument
|
||||
--> justfile:1:9
|
||||
|
|
||||
1 | !include
|
||||
| ^
|
||||
|
@ -20,7 +20,7 @@ pub(crate) use {
|
||||
fs,
|
||||
io::Write,
|
||||
iter,
|
||||
path::{Path, PathBuf},
|
||||
path::{Path, PathBuf, MAIN_SEPARATOR},
|
||||
process::{Command, Stdio},
|
||||
str,
|
||||
},
|
||||
|
@ -72,6 +72,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Unknown setting `foo`
|
||||
--> justfile:1:5
|
||||
|
|
||||
1 | set foo
|
||||
| ^^^
|
||||
@ -86,6 +87,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Unknown setting `if`
|
||||
--> justfile:1:5
|
||||
|
|
||||
1 | set if := 'foo'
|
||||
| ^^
|
||||
@ -106,6 +108,7 @@ test! {
|
||||
justfile: "alias foo := bar\nalias foo := baz\n",
|
||||
stderr: "
|
||||
error: Alias `foo` first defined on line 1 is redefined on line 2
|
||||
--> justfile:2:7
|
||||
|
|
||||
2 | alias foo := baz
|
||||
| ^^^
|
||||
@ -118,6 +121,7 @@ test! {
|
||||
justfile: "alias foo := bar\n",
|
||||
stderr: "
|
||||
error: Alias `foo` has an unknown target `bar`
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | alias foo := bar
|
||||
| ^^^
|
||||
@ -130,6 +134,7 @@ test! {
|
||||
justfile: "bar:\n echo bar\nalias foo := bar\nfoo:\n echo foo",
|
||||
stderr: "
|
||||
error: Alias `foo` defined on line 3 shadows recipe `foo` defined on line 4
|
||||
--> justfile:3:7
|
||||
|
|
||||
3 | alias foo := bar
|
||||
| ^^^
|
||||
@ -264,6 +269,7 @@ test! {
|
||||
justfile: "bar:\nhello:\nfoo: bar baaaaaaaz hello",
|
||||
stderr: "
|
||||
error: Recipe `foo` has unknown dependency `baaaaaaaz`
|
||||
--> justfile:3:10
|
||||
|
|
||||
3 | foo: bar baaaaaaaz hello
|
||||
| ^^^^^^^^^
|
||||
@ -290,6 +296,7 @@ test! {
|
||||
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 100
|
||||
--> justfile:2:6
|
||||
|
|
||||
2 | a := `exit 100`
|
||||
| ^^^^^^^^^^
|
||||
@ -302,6 +309,7 @@ test! {
|
||||
justfile: "b := a\na := `echo hello`\nbar:\n echo '{{`exit 200`}}'",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:4:10
|
||||
|
|
||||
4 | echo '{{`exit 200`}}'
|
||||
| ^^^^^^^^^^
|
||||
@ -314,6 +322,7 @@ test! {
|
||||
justfile: "f:\n 無{{`exit 200`}}",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:2:7
|
||||
|
|
||||
2 | 無{{`exit 200`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -328,6 +337,7 @@ test! {
|
||||
\techo {{`exit 200`}}
|
||||
",
|
||||
stderr: " error: Backtick failed with exit code 200
|
||||
--> justfile:2:9
|
||||
|
|
||||
2 | echo {{`exit 200`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -342,6 +352,7 @@ test! {
|
||||
\techo {{\t`exit 200`}}
|
||||
",
|
||||
stderr: "error: Backtick failed with exit code 200
|
||||
--> justfile:2:10
|
||||
|
|
||||
2 | echo {{ `exit 200`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -357,6 +368,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:2:10
|
||||
|
|
||||
2 | echo {{ `exit 200`}}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -372,6 +384,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:2:13
|
||||
|
|
||||
2 | echo 😬{{`exit 200`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -387,6 +400,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:2:24
|
||||
|
|
||||
2 | echo 😬鎌鼬{{ `exit 200 # abc`}} 😬鎌鼬
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -410,6 +424,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 200
|
||||
--> justfile:10:10
|
||||
|
|
||||
10 | echo '{{`exit 200`}}'
|
||||
| ^^^^^^^^^^
|
||||
@ -426,6 +441,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 123
|
||||
--> justfile:4:9
|
||||
|
|
||||
4 | echo {{`exit 123`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -442,6 +458,7 @@ test! {
|
||||
stderr: "
|
||||
echo hello
|
||||
error: Backtick failed with exit code 123
|
||||
--> justfile:3:9
|
||||
|
|
||||
3 | echo {{`exit 123`}}
|
||||
| ^^^^^^^^^^
|
||||
@ -458,6 +475,7 @@ a := `exit 222`",
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Backtick failed with exit code 222
|
||||
--> justfile:4:6
|
||||
|
|
||||
4 | a := `exit 222`
|
||||
| ^^^^^^^^^^
|
||||
@ -573,6 +591,7 @@ test! {
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: "error: Unknown start of token:
|
||||
--> justfile:10:1
|
||||
|
|
||||
10 | ???
|
||||
| ^
|
||||
@ -677,8 +696,7 @@ test! {
|
||||
justfile: "b := a\na := `exit 100`\nbar:\n echo '{{`exit 200`}}'",
|
||||
args: ("--color", "always"),
|
||||
stdout: "",
|
||||
stderr: "\u{1b}[1;31merror\u{1b}[0m: \u{1b}[1mBacktick failed with exit code 100\u{1b}[0m
|
||||
|\n2 | a := `exit 100`\n | \u{1b}[1;31m^^^^^^^^^^\u{1b}[0m\n",
|
||||
stderr: "\u{1b}[1;31merror\u{1b}[0m: \u{1b}[1mBacktick failed with exit code 100\u{1b}[0m\n \u{1b}[1;34m-->\u{1b}[0m justfile:2:6\n \u{1b}[1;34m|\u{1b}[0m\n\u{1b}[1;34m2 |\u{1b}[0m a := `exit 100`\n \u{1b}[1;34m|\u{1b}[0m \u{1b}[1;31m^^^^^^^^^^\u{1b}[0m\n",
|
||||
status: 100,
|
||||
}
|
||||
|
||||
@ -688,6 +706,7 @@ test! {
|
||||
args: ("--color", "never"),
|
||||
stdout: "",
|
||||
stderr: "error: Backtick failed with exit code 100
|
||||
--> justfile:2:6
|
||||
|
|
||||
2 | a := `exit 100`
|
||||
| ^^^^^^^^^^
|
||||
@ -701,6 +720,7 @@ test! {
|
||||
args: ("--color", "auto"),
|
||||
stdout: "",
|
||||
stderr: "error: Backtick failed with exit code 100
|
||||
--> justfile:2:6
|
||||
|
|
||||
2 | a := `exit 100`
|
||||
| ^^^^^^^^^^
|
||||
@ -739,6 +759,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "error: Found a mix of tabs and spaces in leading whitespace: `␉␠`
|
||||
Leading whitespace may consist of tabs or spaces, but not both
|
||||
--> justfile:2:1
|
||||
|
|
||||
2 | echo hello
|
||||
| ^^^^^
|
||||
@ -751,6 +772,7 @@ test! {
|
||||
justfile: "bar:\n\t\techo hello\n\t\t\techo goodbye",
|
||||
stdout: "",
|
||||
stderr: "error: Recipe line has extra leading whitespace
|
||||
--> justfile:3:3
|
||||
|
|
||||
3 | echo goodbye
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -764,6 +786,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "error: Recipe line has inconsistent leading whitespace. \
|
||||
Recipe started with `␉␉` but found line with `␉␠`
|
||||
--> justfile:3:1
|
||||
|
|
||||
3 | echo goodbye
|
||||
| ^^^^^
|
||||
@ -776,6 +799,7 @@ test! {
|
||||
justfile: "bar:\nhello baz arg='foo' bar:",
|
||||
stdout: "",
|
||||
stderr: "error: Non-default parameter `bar` follows default parameter
|
||||
--> justfile:2:21
|
||||
|
|
||||
2 | hello baz arg='foo' bar:
|
||||
| ^^^
|
||||
@ -788,6 +812,7 @@ test! {
|
||||
justfile: "bar:\nhello baz +arg bar:",
|
||||
stdout: "",
|
||||
stderr: "error: Parameter `bar` follows variadic parameter
|
||||
--> justfile:2:16
|
||||
|
|
||||
2 | hello baz +arg bar:
|
||||
| ^^^
|
||||
@ -800,6 +825,7 @@ test! {
|
||||
justfile: "bar:\nhello baz *arg bar:",
|
||||
stdout: "",
|
||||
stderr: "error: Parameter `bar` follows variadic parameter
|
||||
--> justfile:2:16
|
||||
|
|
||||
2 | hello baz *arg bar:
|
||||
| ^^^
|
||||
@ -1172,6 +1198,7 @@ bar:"#,
|
||||
args: ("bar"),
|
||||
stdout: "",
|
||||
stderr: r#"error: Call to unknown function `foo`
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo := foo() + "hello"
|
||||
| ^^^
|
||||
@ -1188,6 +1215,7 @@ test! {
|
||||
args: ("b"),
|
||||
stdout: "",
|
||||
stderr: "error: Dependency `a` got 0 arguments but takes 1 argument
|
||||
--> justfile:2:4
|
||||
|
|
||||
2 | b: a
|
||||
| ^
|
||||
@ -1204,6 +1232,7 @@ test! {
|
||||
args: ("b"),
|
||||
stdout: "",
|
||||
stderr: "error: Dependency `a` got 0 arguments but takes at least 1 argument
|
||||
--> justfile:2:4
|
||||
|
|
||||
2 | b: a
|
||||
| ^
|
||||
@ -1220,6 +1249,7 @@ test! {
|
||||
args: ("b"),
|
||||
stdout: "",
|
||||
stderr: "error: Dependency `a` got 3 arguments but takes at most 2 arguments
|
||||
--> justfile:2:5
|
||||
|
|
||||
2 | b: (a '0' '1' '2')
|
||||
| ^
|
||||
@ -1233,6 +1263,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Recipe `a` has duplicate parameter `foo`
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | a foo foo:
|
||||
| ^^^
|
||||
@ -1246,6 +1277,7 @@ test! {
|
||||
args: ("b"),
|
||||
stdout: "",
|
||||
stderr: "error: Recipe `b` first defined on line 1 is redefined on line 2
|
||||
--> justfile:2:1
|
||||
|
|
||||
2 | b:
|
||||
| ^
|
||||
@ -1259,6 +1291,7 @@ test! {
|
||||
args: ("foo"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `a` has multiple definitions
|
||||
--> justfile:2:1
|
||||
|
|
||||
2 | a := 'hello'
|
||||
| ^
|
||||
@ -1273,6 +1306,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "error: Expected '&&', comment, end of file, end of line, \
|
||||
identifier, or '(', but found string
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | foo: 'bar'
|
||||
| ^^^^^
|
||||
@ -1286,6 +1320,7 @@ test! {
|
||||
args: ("foo"),
|
||||
stdout: "",
|
||||
stderr: "error: Expected '*', ':', '$', identifier, or '+', but found string
|
||||
--> justfile:1:5
|
||||
|
|
||||
1 | foo 'bar'
|
||||
| ^^^^^
|
||||
@ -1299,6 +1334,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Recipe `a` depends on itself
|
||||
--> justfile:1:4
|
||||
|
|
||||
1 | a: a
|
||||
| ^
|
||||
@ -1312,6 +1348,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Recipe `d` has circular dependency `a -> b -> c -> d -> a`
|
||||
--> justfile:4:4
|
||||
|
|
||||
4 | d: a
|
||||
| ^
|
||||
@ -1325,6 +1362,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `z` is defined in terms of itself
|
||||
--> justfile:1:1
|
||||
|
|
||||
1 | z := z
|
||||
| ^
|
||||
@ -1338,6 +1376,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `x` depends on its own value: `x -> y -> z -> x`
|
||||
--> justfile:1:1
|
||||
|
|
||||
1 | x := y
|
||||
| ^
|
||||
@ -1357,6 +1396,7 @@ test! {
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `x` depends on its own value: `x -> y -> x`
|
||||
--> justfile:2:1
|
||||
|
|
||||
2 | x := y
|
||||
| ^
|
||||
@ -1461,6 +1501,7 @@ foo *a +b:
|
||||
",
|
||||
stdout: "",
|
||||
stderr: "error: Expected \':\' or \'=\', but found \'+\'
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo *a +b:
|
||||
| ^
|
||||
@ -1476,6 +1517,7 @@ foo +a *b:
|
||||
",
|
||||
stdout: "",
|
||||
stderr: "error: Expected \':\' or \'=\', but found \'*\'
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo +a *b:
|
||||
| ^
|
||||
@ -1509,6 +1551,7 @@ a: x y
|
||||
",
|
||||
stdout: "",
|
||||
stderr: "error: Recipe `a` has unknown dependency `y`
|
||||
--> justfile:3:6
|
||||
|
|
||||
3 | a: x y
|
||||
| ^
|
||||
@ -1666,6 +1709,7 @@ X := "\'"
|
||||
"#,
|
||||
stdout: "",
|
||||
stderr: r#"error: `\'` is not a valid escape sequence
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | X := "\'"
|
||||
| ^^^^
|
||||
@ -1680,6 +1724,7 @@ test! {
|
||||
",
|
||||
stdout: "",
|
||||
stderr: r#"error: Variable `bar` not defined
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | foo x=bar:
|
||||
| ^^^
|
||||
@ -1694,6 +1739,7 @@ foo x=bar():
|
||||
",
|
||||
stdout: "",
|
||||
stderr: r#"error: Call to unknown function `bar`
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | foo x=bar():
|
||||
| ^^^
|
||||
@ -1750,6 +1796,7 @@ test! {
|
||||
",
|
||||
stderr: r#"
|
||||
error: Unterminated interpolation
|
||||
--> justfile:2:8
|
||||
|
|
||||
2 | echo {{
|
||||
| ^^
|
||||
@ -1765,6 +1812,7 @@ test! {
|
||||
",
|
||||
stderr: r#"
|
||||
error: Unterminated interpolation
|
||||
--> justfile:2:8
|
||||
|
|
||||
2 | echo {{
|
||||
| ^^
|
||||
@ -1779,6 +1827,7 @@ assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
|
||||
",
|
||||
stderr: r#"
|
||||
error: Unknown start of token:
|
||||
--> justfile:1:25
|
||||
|
|
||||
1 | assembly_source_files = %(wildcard src/arch/$(arch)/*.s)
|
||||
| ^
|
||||
@ -1877,6 +1926,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Expected '*', ':', '$', identifier, or '+', but found '='
|
||||
--> justfile:1:5
|
||||
|
|
||||
1 | foo = 'bar'
|
||||
| ^
|
||||
@ -2074,6 +2124,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Variable `a` not defined
|
||||
--> justfile:3:9
|
||||
|
|
||||
3 | bar a b=a:
|
||||
| ^
|
||||
|
@ -72,6 +72,7 @@ fn newline_escape_deps_invalid_esc() {
|
||||
.stderr(
|
||||
"
|
||||
error: `\\ ` is not a valid escape sequence
|
||||
--> justfile:1:11
|
||||
|
|
||||
1 | default: a\\ b
|
||||
| ^
|
||||
@ -92,6 +93,7 @@ fn newline_escape_unpaired_linefeed() {
|
||||
.stderr(
|
||||
"
|
||||
error: Unpaired carriage return
|
||||
--> justfile:1:9
|
||||
|
|
||||
1 | default:\\\ra
|
||||
| ^
|
||||
|
@ -53,6 +53,7 @@ hello:
|
||||
"#,
|
||||
stderr: r#"
|
||||
error: Unknown attribute `unknown-attribute`
|
||||
--> justfile:2:2
|
||||
|
|
||||
2 | [unknown-attribute]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -70,6 +71,7 @@ hello:
|
||||
"#,
|
||||
stderr: r#"
|
||||
error: Expected identifier, but found ']'
|
||||
--> justfile:2:2
|
||||
|
|
||||
2 | []
|
||||
| ^
|
||||
@ -87,6 +89,7 @@ hello:
|
||||
"#,
|
||||
stderr: r#"
|
||||
error: Expected '@', '[', or identifier, but found comment
|
||||
--> justfile:2:1
|
||||
|
|
||||
2 | # This is a doc comment
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -103,7 +106,7 @@ test! {
|
||||
hello:
|
||||
@exit 100
|
||||
"#,
|
||||
stderr: "error: Expected '@', '[', or identifier, but found end of line\n |\n2 | \n | ^\n",
|
||||
stderr: "error: Expected '@', '[', or identifier, but found end of line\n --> justfile:2:1\n |\n2 | \n | ^\n",
|
||||
status: EXIT_FAILURE,
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ fn bugfix() {
|
||||
#[cfg(not(windows))]
|
||||
const RECURSION_LIMIT_REACHED: &str = "
|
||||
error: Parsing recursion depth exceeded
|
||||
--> justfile:1:265
|
||||
|
|
||||
1 | foo: (x ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
|
||||
| ^
|
||||
@ -24,6 +25,7 @@ error: Parsing recursion depth exceeded
|
||||
#[cfg(windows)]
|
||||
const RECURSION_LIMIT_REACHED: &str = "
|
||||
error: Parsing recursion depth exceeded
|
||||
--> justfile:1:57
|
||||
|
|
||||
1 | foo: (x ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((
|
||||
| ^
|
||||
|
@ -30,6 +30,7 @@ test! {
|
||||
args: ("--show", "f"),
|
||||
stderr: "
|
||||
error: Alias `f` has an unknown target `foo`
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | alias f := foo
|
||||
| ^
|
||||
|
@ -48,6 +48,7 @@ fn no_rhs_once() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected backtick, identifier, '(', '/', or string, but found end of file
|
||||
--> justfile:1:11
|
||||
|
|
||||
1 | x := 'a' /
|
||||
| ^
|
||||
@ -69,6 +70,7 @@ fn default_un_parenthesized() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected '*', ':', '$', identifier, or '+', but found '/'
|
||||
--> justfile:1:11
|
||||
|
|
||||
1 | foo x='a' / 'b':
|
||||
| ^
|
||||
@ -90,6 +92,7 @@ fn no_lhs_un_parenthesized() {
|
||||
.stderr(
|
||||
"
|
||||
error: Expected backtick, identifier, '(', or string, but found '/'
|
||||
--> justfile:1:7
|
||||
|
|
||||
1 | foo x=/ 'a' / 'b':
|
||||
| ^
|
||||
|
@ -88,6 +88,7 @@ a:"#,
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: `\\q` is not a valid escape sequence
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | x := \"\\q\"
|
||||
| ^^^^
|
||||
@ -108,6 +109,7 @@ a:
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `foo` not defined
|
||||
--> justfile:6:11
|
||||
|
|
||||
6 | echo '{{foo}}'
|
||||
| ^^^
|
||||
@ -128,6 +130,7 @@ a:
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `bar` not defined
|
||||
--> justfile:3:13
|
||||
|
|
||||
3 | whatever' + bar
|
||||
| ^^^
|
||||
@ -165,6 +168,7 @@ a:
|
||||
args: ("a"),
|
||||
stdout: "",
|
||||
stderr: "error: Variable `b` not defined
|
||||
--> justfile:5:10
|
||||
|
|
||||
5 | echo {{b}}
|
||||
| ^
|
||||
@ -181,6 +185,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Unterminated string
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | a b= ':
|
||||
| ^
|
||||
@ -197,6 +202,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: r#"
|
||||
error: Unterminated string
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | a b= ":
|
||||
| ^
|
||||
@ -212,6 +218,7 @@ test! {
|
||||
",
|
||||
stderr: r#"
|
||||
error: Unterminated backtick
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo a= `echo blaaaaaah:
|
||||
| ^
|
||||
@ -228,6 +235,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: "
|
||||
error: Unterminated string
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | a b= ''':
|
||||
| ^^^
|
||||
@ -244,6 +252,7 @@ test! {
|
||||
stdout: "",
|
||||
stderr: r#"
|
||||
error: Unterminated string
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | a b= """:
|
||||
| ^^^
|
||||
@ -259,6 +268,7 @@ test! {
|
||||
",
|
||||
stderr: r#"
|
||||
error: Unterminated backtick
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo a= ```echo blaaaaaah:
|
||||
| ^^^
|
||||
@ -374,6 +384,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Backticks may not start with `#!`
|
||||
--> justfile:1:6
|
||||
|
|
||||
1 | x := `#!/usr/bin/env sh`
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -47,6 +47,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Recipe `foo` depends on itself
|
||||
--> justfile:1:9
|
||||
|
|
||||
1 | foo: && foo
|
||||
| ^^^
|
||||
@ -61,6 +62,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Recipe `foo` has unknown dependency `bar`
|
||||
--> justfile:1:9
|
||||
|
|
||||
1 | foo: && bar
|
||||
| ^^^
|
||||
@ -77,6 +79,7 @@ test! {
|
||||
",
|
||||
stderr: "
|
||||
error: Variable `y` not defined
|
||||
--> justfile:3:14
|
||||
|
|
||||
3 | foo: && (bar y)
|
||||
| ^
|
||||
|
@ -7,6 +7,7 @@ fn parameter_default_unknown_variable_in_expression() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:8
|
||||
|
|
||||
1 | foo a=(b+''):
|
||||
| ^
|
||||
@ -27,6 +28,7 @@ fn unknown_variable_in_unary_call() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `a` not defined
|
||||
--> justfile:1:15
|
||||
|
|
||||
1 | foo x=env_var(a):
|
||||
| ^
|
||||
@ -47,6 +49,7 @@ fn unknown_first_variable_in_binary_call() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `a` not defined
|
||||
--> justfile:1:26
|
||||
|
|
||||
1 | foo x=env_var_or_default(a, b):
|
||||
| ^
|
||||
@ -67,6 +70,7 @@ fn unknown_second_variable_in_binary_call() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `b` not defined
|
||||
--> justfile:1:30
|
||||
|
|
||||
1 | foo x=env_var_or_default('', b):
|
||||
| ^
|
||||
@ -87,6 +91,7 @@ fn unknown_variable_in_ternary_call() {
|
||||
.stderr(
|
||||
"
|
||||
error: Variable `a` not defined
|
||||
--> justfile:1:15
|
||||
|
|
||||
1 | foo x=replace(a, b, c):
|
||||
| ^
|
||||
|
Loading…
Reference in New Issue
Block a user