This commit is contained in:
Yuri Astrakhan 2023-06-12 12:53:55 -04:00 committed by GitHub
parent 6a407813b4
commit a1220c63e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 153 additions and 265 deletions

View File

@ -43,7 +43,7 @@ impl<'src> Analyzer<'src> {
let settings = Settings::from_setting_iter(self.sets.into_iter().map(|(_, set)| set.value)); let settings = Settings::from_setting_iter(self.sets.into_iter().map(|(_, set)| set.value));
let mut recipe_table: Table<'src, UnresolvedRecipe<'src>> = Default::default(); let mut recipe_table: Table<'src, UnresolvedRecipe<'src>> = Table::default();
AssignmentResolver::resolve_assignments(&self.assignments)?; AssignmentResolver::resolve_assignments(&self.assignments)?;

View File

@ -24,37 +24,27 @@ impl Display for CompileError<'_> {
use CompileErrorKind::*; use CompileErrorKind::*;
match &*self.kind { match &*self.kind {
AliasInvalidAttribute { alias, attr } => { AliasInvalidAttribute { alias, attr } => write!(
write!(
f, f,
"Alias {} has an invalid attribute `{}`", "Alias {alias} has an invalid attribute `{}`",
alias, attr.to_str(),
attr.to_str() ),
)?; AliasShadowsRecipe { alias, recipe_line } => write!(
}
AliasShadowsRecipe { alias, recipe_line } => {
write!(
f, f,
"Alias `{}` defined on line {} shadows recipe `{}` defined on line {}", "Alias `{alias}` defined on line {} shadows recipe `{alias}` defined on line {}",
alias,
self.token.line.ordinal(), self.token.line.ordinal(),
alias,
recipe_line.ordinal(), recipe_line.ordinal(),
)?; ),
} BacktickShebang => write!(f, "Backticks may not start with `#!`"),
BacktickShebang => {
write!(f, "Backticks may not start with `#!`")?;
}
CircularRecipeDependency { recipe, ref circle } => { CircularRecipeDependency { recipe, ref circle } => {
if circle.len() == 2 { if circle.len() == 2 {
write!(f, "Recipe `{recipe}` depends on itself")?; write!(f, "Recipe `{recipe}` depends on itself")
} else { } else {
write!( write!(
f, f,
"Recipe `{}` has circular dependency `{}`", "Recipe `{recipe}` has circular dependency `{}`",
recipe,
circle.join(" -> ") circle.join(" -> ")
)?; )
} }
} }
CircularVariableDependency { CircularVariableDependency {
@ -62,14 +52,13 @@ impl Display for CompileError<'_> {
ref circle, ref circle,
} => { } => {
if circle.len() == 2 { if circle.len() == 2 {
write!(f, "Variable `{variable}` is defined in terms of itself")?; write!(f, "Variable `{variable}` is defined in terms of itself")
} else { } else {
write!( write!(
f, f,
"Variable `{}` depends on its own value: `{}`", "Variable `{variable}` depends on its own value: `{}`",
variable, circle.join(" -> "),
circle.join(" -> ") )
)?;
} }
} }
DependencyArgumentCountMismatch { DependencyArgumentCountMismatch {
@ -80,206 +69,146 @@ impl Display for CompileError<'_> {
} => { } => {
write!( write!(
f, f,
"Dependency `{}` got {} {} but takes ", "Dependency `{dependency}` got {found} {} but takes ",
dependency,
found,
Count("argument", *found), Count("argument", *found),
)?; )?;
if min == max { if min == max {
let expected = min; let expected = min;
write!(f, "{expected} {}", Count("argument", *expected))?; write!(f, "{expected} {}", Count("argument", *expected))
} else if found < min { } else if found < min {
write!(f, "at least {min} {}", Count("argument", *min))?; write!(f, "at least {min} {}", Count("argument", *min))
} else { } else {
write!(f, "at most {max} {}", Count("argument", *max))?; write!(f, "at most {max} {}", Count("argument", *max))
} }
} }
DuplicateAlias { alias, first } => { DuplicateAlias { alias, first } => write!(
write!(
f, f,
"Alias `{}` first defined on line {} is redefined on line {}", "Alias `{alias}` first defined on line {} is redefined on line {}",
alias,
first.ordinal(), first.ordinal(),
self.token.line.ordinal(), self.token.line.ordinal(),
)?; ),
} DuplicateAttribute { attribute, first } => write!(
DuplicateAttribute { attribute, first } => {
write!(
f, f,
"Recipe attribute `{}` first used on line {} is duplicated on line {}", "Recipe attribute `{attribute}` first used on line {} is duplicated on line {}",
attribute,
first.ordinal(), first.ordinal(),
self.token.line.ordinal(), self.token.line.ordinal(),
)?; ),
}
DuplicateParameter { recipe, parameter } => { DuplicateParameter { recipe, parameter } => {
write!(f, "Recipe `{recipe}` has duplicate parameter `{parameter}`")?; write!(f, "Recipe `{recipe}` has duplicate parameter `{parameter}`")
} }
DuplicateRecipe { recipe, first } => { DuplicateRecipe { recipe, first } => write!(
write!(
f, f,
"Recipe `{}` first defined on line {} is redefined on line {}", "Recipe `{recipe}` first defined on line {} is redefined on line {}",
recipe,
first.ordinal(),
self.token.line.ordinal()
)?;
}
DuplicateSet { setting, first } => {
write!(
f,
"Setting `{}` first set on line {} is redefined on line {}",
setting,
first.ordinal(), first.ordinal(),
self.token.line.ordinal(), self.token.line.ordinal(),
)?; ),
} DuplicateSet { setting, first } => write!(
f,
"Setting `{setting}` first set on line {} is redefined on line {}",
first.ordinal(),
self.token.line.ordinal(),
),
DuplicateVariable { variable } => { DuplicateVariable { variable } => {
write!(f, "Variable `{variable}` has multiple definitions")?; write!(f, "Variable `{variable}` has multiple definitions")
} }
ExpectedKeyword { expected, found } => { ExpectedKeyword { expected, found } => {
let expected = List::or_ticked(expected);
if found.kind == TokenKind::Identifier { if found.kind == TokenKind::Identifier {
write!( write!(
f, f,
"Expected keyword {} but found identifier `{}`", "Expected keyword {expected} but found identifier `{}`",
List::or_ticked(expected),
found.lexeme() found.lexeme()
)?; )
} else { } else {
write!( write!(f, "Expected keyword {expected} but found `{}`", found.kind)
f,
"Expected keyword {} but found `{}`",
List::or_ticked(expected),
found.kind
)?;
} }
} }
ExtraLeadingWhitespace => { ExtraLeadingWhitespace => write!(f, "Recipe line has extra leading whitespace"),
write!(f, "Recipe line has extra leading whitespace")?;
}
FunctionArgumentCountMismatch { FunctionArgumentCountMismatch {
function, function,
found, found,
expected, expected,
} => { } => write!(
write!(
f, f,
"Function `{}` called with {} {} but takes {}", "Function `{function}` called with {found} {} but takes {}",
function,
found,
Count("argument", *found), Count("argument", *found),
expected.display(), expected.display(),
)?; ),
} InconsistentLeadingWhitespace { expected, found } => write!(
InconsistentLeadingWhitespace { expected, found } => {
write!(
f, f,
"Recipe line has inconsistent leading whitespace. Recipe started with `{}` but found \ "Recipe line has inconsistent leading whitespace. Recipe started with `{}` but found \
line with `{}`", line with `{}`",
ShowWhitespace(expected), ShowWhitespace(expected),
ShowWhitespace(found) ShowWhitespace(found)
)?; ),
} Internal { ref message } => write!(
Internal { ref message } => {
write!(
f, f,
"Internal error, this may indicate a bug in just: {message}\n\ "Internal error, this may indicate a bug in just: {message}\n\
consider filing an issue: https://github.com/casey/just/issues/new" consider filing an issue: https://github.com/casey/just/issues/new"
)?; ),
} InvalidEscapeSequence { character } => write!(
InvalidEscapeSequence { character } => { f,
let representation = match character { "`\\{}` is not a valid escape sequence",
match character {
'`' => r"\`".to_owned(), '`' => r"\`".to_owned(),
'\\' => r"\".to_owned(), '\\' => r"\".to_owned(),
'\'' => r"'".to_owned(), '\'' => r"'".to_owned(),
'"' => r#"""#.to_owned(), '"' => r#"""#.to_owned(),
_ => character.escape_default().collect(), _ => character.escape_default().collect(),
};
write!(f, "`\\{representation}` is not a valid escape sequence")?;
} }
),
MismatchedClosingDelimiter { MismatchedClosingDelimiter {
open, open,
open_line, open_line,
close, close,
} => { } => write!(
write!(
f, f,
"Mismatched closing delimiter `{}`. (Did you mean to close the `{}` on line {}?)", "Mismatched closing delimiter `{}`. (Did you mean to close the `{}` on line {}?)",
close.close(), close.close(),
open.open(), open.open(),
open_line.ordinal(), open_line.ordinal(),
)?; ),
} MixedLeadingWhitespace { whitespace } => write!(
MixedLeadingWhitespace { whitespace } => {
write!(
f, f,
"Found a mix of tabs and spaces in leading whitespace: `{}`\nLeading whitespace may \ "Found a mix of tabs and spaces in leading whitespace: `{}`\nLeading whitespace may \
consist of tabs or spaces, but not both", consist of tabs or spaces, but not both",
ShowWhitespace(whitespace) ShowWhitespace(whitespace)
)?; ),
}
ParameterFollowsVariadicParameter { parameter } => { ParameterFollowsVariadicParameter { parameter } => {
write!(f, "Parameter `{parameter}` follows variadic parameter")?; write!(f, "Parameter `{parameter}` follows variadic parameter")
} }
ParsingRecursionDepthExceeded => { ParsingRecursionDepthExceeded => write!(f, "Parsing recursion depth exceeded"),
write!(f, "Parsing recursion depth exceeded")?; RequiredParameterFollowsDefaultParameter { parameter } => write!(
}
RequiredParameterFollowsDefaultParameter { parameter } => {
write!(
f, f,
"Non-default parameter `{parameter}` follows default parameter" "Non-default parameter `{parameter}` follows default parameter"
)?; ),
} UndefinedVariable { variable } => write!(f, "Variable `{variable}` not defined"),
UndefinedVariable { variable } => { UnexpectedCharacter { expected } => write!(f, "Expected character `{expected}`"),
write!(f, "Variable `{variable}` not defined")?;
}
UnexpectedCharacter { expected } => {
write!(f, "Expected character `{expected}`")?;
}
UnexpectedClosingDelimiter { close } => { UnexpectedClosingDelimiter { close } => {
write!(f, "Unexpected closing delimiter `{}`", close.close())?; write!(f, "Unexpected closing delimiter `{}`", close.close())
} }
UnexpectedEndOfToken { expected } => { UnexpectedEndOfToken { expected } => {
write!(f, "Expected character `{expected}` but found end-of-file")?; write!(f, "Expected character `{expected}` but found end-of-file")
} }
UnexpectedToken { UnexpectedToken {
ref expected, ref expected,
found, found,
} => { } => write!(f, "Expected {}, but found {found}", List::or(expected)),
write!(f, "Expected {}, but found {found}", List::or(expected))?;
}
UnknownAliasTarget { alias, target } => { UnknownAliasTarget { alias, target } => {
write!(f, "Alias `{alias}` has an unknown target `{target}`")?; write!(f, "Alias `{alias}` has an unknown target `{target}`")
}
UnknownAttribute { attribute } => {
write!(f, "Unknown attribute `{attribute}`")?;
} }
UnknownAttribute { attribute } => write!(f, "Unknown attribute `{attribute}`"),
UnknownDependency { recipe, unknown } => { UnknownDependency { recipe, unknown } => {
write!(f, "Recipe `{recipe}` has unknown dependency `{unknown}`",)?; write!(f, "Recipe `{recipe}` has unknown dependency `{unknown}`")
} }
UnknownFunction { function } => { UnknownFunction { function } => write!(f, "Call to unknown function `{function}`"),
write!(f, "Call to unknown function `{function}`")?; UnknownSetting { setting } => write!(f, "Unknown setting `{setting}`"),
UnknownStartOfToken => write!(f, "Unknown start of token:"),
UnpairedCarriageReturn => write!(f, "Unpaired carriage return"),
UnterminatedBacktick => write!(f, "Unterminated backtick"),
UnterminatedInterpolation => write!(f, "Unterminated interpolation"),
UnterminatedString => write!(f, "Unterminated string"),
} }
UnknownSetting { setting } => {
write!(f, "Unknown setting `{setting}`")?;
}
UnknownStartOfToken => {
write!(f, "Unknown start of token:")?;
}
UnpairedCarriageReturn => {
write!(f, "Unpaired carriage return")?;
}
UnterminatedBacktick => {
write!(f, "Unterminated backtick")?;
}
UnterminatedInterpolation => {
write!(f, "Unterminated interpolation")?;
}
UnterminatedString => {
write!(f, "Unterminated string")?;
}
}
Ok(())
} }
} }

View File

@ -11,6 +11,7 @@ pub(crate) const CHOOSE_HELP: &str = "Select one or more recipes to run using a
of $JUST_CHOOSER, falling back to `fzf`"; of $JUST_CHOOSER, falling back to `fzf`";
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[allow(clippy::struct_excessive_bools)]
pub(crate) struct Config { pub(crate) struct Config {
pub(crate) check: bool, pub(crate) check: bool,
pub(crate) color: Color, pub(crate) color: Color,

View File

@ -1,6 +1,3 @@
// `Self` cannot be used where type takes generic arguments
#![allow(clippy::use_self)]
use super::*; use super::*;
pub struct Enclosure<T: Display> { pub struct Enclosure<T: Display> {

View File

@ -238,30 +238,21 @@ impl<'src> ColorDisplay for Error<'src> {
let expected = min; let expected = min;
write!( write!(
f, f,
"Recipe `{}` got {} {} but {}takes {}", "Recipe `{recipe}` got {found} {} but {}takes {expected}",
recipe,
found,
Count("argument", *found), Count("argument", *found),
if expected < found { "only " } else { "" }, if expected < found { "only " } else { "" }
expected
)?; )?;
} else if found < min { } else if found < min {
write!( write!(
f, f,
"Recipe `{}` got {} {} but takes at least {}", "Recipe `{recipe}` got {found} {} but takes at least {min}",
recipe, Count("argument", *found)
found,
Count("argument", *found),
min
)?; )?;
} else if found > max { } else if found > max {
write!( write!(
f, f,
"Recipe `{}` got {} {} but takes at most {}", "Recipe `{recipe}` got {found} {} but takes at most {max}",
recipe, Count("argument", *found)
found,
Count("argument", *found),
max
)?; )?;
} }
} }
@ -306,35 +297,29 @@ impl<'src> ColorDisplay for Error<'src> {
} => { } => {
write!( write!(
f, f,
"Chooser `{} {} {}` invocation failed: {}", "Chooser `{shell_binary} {shell_arguments} {}` invocation failed: {io_error}",
shell_binary,
shell_arguments,
chooser.to_string_lossy(), chooser.to_string_lossy(),
io_error,
)?; )?;
} }
ChooserRead { chooser, io_error } => { ChooserRead { chooser, io_error } => {
write!( write!(
f, f,
"Failed to read output from chooser `{}`: {}", "Failed to read output from chooser `{}`: {io_error}",
chooser.to_string_lossy(), chooser.to_string_lossy()
io_error
)?; )?;
} }
ChooserStatus { chooser, status } => { ChooserStatus { chooser, status } => {
write!( write!(
f, f,
"Chooser `{}` failed: {}", "Chooser `{}` failed: {status}",
chooser.to_string_lossy(), chooser.to_string_lossy()
status
)?; )?;
} }
ChooserWrite { chooser, io_error } => { ChooserWrite { chooser, io_error } => {
write!( write!(
f, f,
"Failed to write to chooser `{}`: {}", "Failed to write to chooser `{}`: {io_error}",
chooser.to_string_lossy(), chooser.to_string_lossy()
io_error
)?; )?;
} }
CircularInclude { current, include } => { CircularInclude { current, include } => {
@ -365,13 +350,12 @@ impl<'src> ColorDisplay for Error<'src> {
} => { } => {
write!( write!(
f, f,
"Failed to invoke {}: {}", "Failed to invoke {}: {io_error}",
iter::once(binary) iter::once(binary)
.chain(arguments) .chain(arguments)
.map(|value| Enclosure::tick(value.to_string_lossy()).to_string()) .map(|value| Enclosure::tick(value.to_string_lossy()).to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(" "), .join(" "),
io_error,
)?; )?;
} }
CommandStatus { CommandStatus {
@ -381,13 +365,12 @@ impl<'src> ColorDisplay for Error<'src> {
} => { } => {
write!( write!(
f, f,
"Command {} failed: {}", "Command {} failed: {status}",
iter::once(binary) iter::once(binary)
.chain(arguments) .chain(arguments)
.map(|value| Enclosure::tick(value.to_string_lossy()).to_string()) .map(|value| Enclosure::tick(value.to_string_lossy()).to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(" "), .join(" "),
status,
)?; )?;
} }
Compile { compile_error } => Display::fmt(compile_error, f)?, Compile { compile_error } => Display::fmt(compile_error, f)?,
@ -446,9 +429,7 @@ impl<'src> ColorDisplay for Error<'src> {
} => { } => {
write!( write!(
f, f,
"Recipe `{}` cannot be used as default recipe since it requires at least {} {}.", "Recipe `{recipe}` cannot be used as default recipe since it requires at least {min_arguments} {}.",
recipe,
min_arguments,
Count("argument", *min_arguments), Count("argument", *min_arguments),
)?; )?;
} }
@ -483,9 +464,8 @@ impl<'src> ColorDisplay for Error<'src> {
FunctionCall { function, message } => { FunctionCall { function, message } => {
write!( write!(
f, f,
"Call to function `{}` failed: {}", "Call to function `{}` failed: {message}",
function.lexeme(), function.lexeme()
message
)?; )?;
} }
IncludeMissingPath { IncludeMissingPath {
@ -532,9 +512,8 @@ impl<'src> ColorDisplay for Error<'src> {
Load { io_error, path } => { Load { io_error, path } => {
write!( write!(
f, f,
"Failed to read justfile at `{}`: {}", "Failed to read justfile at `{}`: {io_error}",
path.display(), path.display()
io_error
)?; )?;
} }
NoChoosableRecipes => { NoChoosableRecipes => {
@ -628,9 +607,8 @@ impl<'src> ColorDisplay for Error<'src> {
WriteJustfile { justfile, io_error } => { WriteJustfile { justfile, io_error } => {
write!( write!(
f, f,
"Failed to write justfile to `{}`: {}", "Failed to write justfile to `{}`: {io_error}",
justfile.display(), justfile.display()
io_error
)?; )?;
} }
} }
@ -642,12 +620,7 @@ impl<'src> ColorDisplay for Error<'src> {
} = self } = self
{ {
writeln!(f)?; writeln!(f)?;
write!( write!(f, "{}:\n just {recipe}", color.message().paint("usage"))?;
f,
"{}:\n just {}",
color.message().paint("usage"),
recipe
)?;
for param in parameters { for param in parameters {
write!(f, " {}", param.color_display(color))?; write!(f, " {}", param.color_display(color))?;
} }

View File

@ -1,6 +1,3 @@
#![allow(unknown_lints)]
#![allow(clippy::unnecessary_wraps)]
use { use {
super::*, super::*,
heck::{ heck::{
@ -208,7 +205,7 @@ fn join(
fn just_executable(_context: &FunctionContext) -> Result<String, String> { fn just_executable(_context: &FunctionContext) -> Result<String, String> {
let exe_path = let exe_path =
std::env::current_exe().map_err(|e| format!("Error getting current executable: {e}"))?; env::current_exe().map_err(|e| format!("Error getting current executable: {e}"))?;
exe_path.to_str().map(str::to_owned).ok_or_else(|| { exe_path.to_str().map(str::to_owned).ok_or_else(|| {
format!( format!(
@ -323,7 +320,7 @@ fn sha256_file(context: &FunctionContext, path: &str) -> Result<String, String>
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
let justpath = context.search.working_directory.join(path); let justpath = context.search.working_directory.join(path);
let mut hasher = Sha256::new(); let mut hasher = Sha256::new();
let mut file = std::fs::File::open(&justpath) let mut file = fs::File::open(&justpath)
.map_err(|err| format!("Failed to open file at `{:?}`: {err}", &justpath.to_str()))?; .map_err(|err| format!("Failed to open file at `{:?}`: {err}", &justpath.to_str()))?;
std::io::copy(&mut file, &mut hasher) std::io::copy(&mut file, &mut hasher)
.map_err(|err| format!("Failed to read file at `{:?}`: {err}", &justpath.to_str()))?; .map_err(|err| format!("Failed to read file at `{:?}`: {err}", &justpath.to_str()))?;

View File

@ -208,7 +208,7 @@ impl<'src> Lexer<'src> {
}; };
CompileError::new( CompileError::new(
token, token,
CompileErrorKind::Internal { Internal {
message: message.into(), message: message.into(),
}, },
) )
@ -773,7 +773,7 @@ impl<'src> Lexer<'src> {
/// Lex a backtick, cooked string, or raw string. /// Lex a backtick, cooked string, or raw string.
/// ///
/// Backtick: `[^`]*` /// Backtick: ``[^`]*``
/// Cooked string: "[^"]*" # also processes escape sequences /// Cooked string: "[^"]*" # also processes escape sequences
/// Raw string: '[^']*' /// Raw string: '[^']*'
fn lex_string(&mut self) -> CompileResult<'src, ()> { fn lex_string(&mut self) -> CompileResult<'src, ()> {

View File

@ -1,16 +1,10 @@
#![deny(clippy::all, clippy::pedantic)] #![deny(clippy::all, clippy::pedantic)]
#![allow( #![allow(
clippy::default_trait_access,
clippy::doc_markdown,
clippy::enum_glob_use, clippy::enum_glob_use,
clippy::let_underscore_untyped, clippy::let_underscore_untyped,
clippy::missing_errors_doc,
clippy::needless_pass_by_value, clippy::needless_pass_by_value,
clippy::non_ascii_literal,
clippy::shadow_unrelated,
clippy::struct_excessive_bools,
clippy::too_many_lines, clippy::too_many_lines,
clippy::type_repetition_in_bounds, clippy::unnecessary_wraps,
clippy::wildcard_imports clippy::wildcard_imports
)] )]

View File

@ -1,6 +1,3 @@
// `Self` cannot be used where type takes generic arguments
#![allow(clippy::use_self)]
use super::*; use super::*;
pub struct List<T: Display, I: Iterator<Item = T> + Clone> { pub struct List<T: Display, I: Iterator<Item = T> + Clone> {

View File

@ -174,15 +174,14 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
if next.kind != Identifier { if next.kind != Identifier {
Err(self.internal_error(format!( Err(self.internal_error(format!(
"Presumed next token would have kind {}, but found {}", "Presumed next token would have kind {Identifier}, but found {}",
Identifier, next.kind next.kind
))?) ))?)
} else if keyword == next.lexeme() { } else if keyword == next.lexeme() {
Ok(()) Ok(())
} else { } else {
Err(self.internal_error(format!( Err(self.internal_error(format!(
"Presumed next token would have lexeme \"{}\", but found \"{}\"", "Presumed next token would have lexeme \"{keyword}\", but found \"{}\"",
keyword,
next.lexeme(), next.lexeme(),
))?) ))?)
} }
@ -196,8 +195,8 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
Ok(next) Ok(next)
} else { } else {
Err(self.internal_error(format!( Err(self.internal_error(format!(
"Presumed next token would have kind {:?}, but found {:?}", "Presumed next token would have kind {kind:?}, but found {:?}",
kind, next.kind next.kind
))?) ))?)
} }
} }
@ -869,7 +868,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
} }
attributes.insert(attribute, name.line); attributes.insert(attribute, name.line);
if !self.accepted(TokenKind::Comma)? { if !self.accepted(Comma)? {
break; break;
} }
} }

View File

@ -1,6 +1,7 @@
use super::*; use super::*;
/// Main entry point into just binary. /// Main entry point into just binary.
#[allow(clippy::missing_errors_doc)]
pub fn run() -> Result<(), i32> { pub fn run() -> Result<(), i32> {
#[cfg(windows)] #[cfg(windows)]
ansi_term::enable_ansi_support().ok(); ansi_term::enable_ansi_support().ok();

View File

@ -6,6 +6,7 @@ pub(crate) const WINDOWS_POWERSHELL_SHELL: &str = "powershell.exe";
pub(crate) const WINDOWS_POWERSHELL_ARGS: &[&str] = &["-NoLogo", "-Command"]; pub(crate) const WINDOWS_POWERSHELL_ARGS: &[&str] = &["-NoLogo", "-Command"];
#[derive(Debug, PartialEq, Serialize, Default)] #[derive(Debug, PartialEq, Serialize, Default)]
#[allow(clippy::struct_excessive_bools)]
pub(crate) struct Settings<'src> { pub(crate) struct Settings<'src> {
pub(crate) allow_duplicate_recipes: bool, pub(crate) allow_duplicate_recipes: bool,
pub(crate) dotenv_load: Option<bool>, pub(crate) dotenv_load: Option<bool>,

View File

@ -116,7 +116,7 @@ fn editor_precedence() {
assert_stdout(&output, JUSTFILE); assert_stdout(&output, JUSTFILE);
let cat = which("cat").unwrap(); let cat = which("cat").unwrap();
let vim = tmp.path().join(format!("vim{}", env::consts::EXE_SUFFIX)); let vim = tmp.path().join(format!("vim{}", EXE_SUFFIX));
#[cfg(unix)] #[cfg(unix)]
std::os::unix::fs::symlink(cat, vim).unwrap(); std::os::unix::fs::symlink(cat, vim).unwrap();
@ -154,7 +154,7 @@ fn editor_working_directory() {
let editor = tmp.path().join("editor"); let editor = tmp.path().join("editor");
let permissions = std::os::unix::fs::PermissionsExt::from_mode(0o700); let permissions = std::os::unix::fs::PermissionsExt::from_mode(0o700);
std::fs::set_permissions(&editor, permissions).unwrap(); fs::set_permissions(&editor, permissions).unwrap();
let output = Command::new(executable_path("just")) let output = Command::new(executable_path("just"))
.current_dir(tmp.path().join("child")) .current_dir(tmp.path().join("child"))
@ -164,8 +164,7 @@ fn editor_working_directory() {
.unwrap(); .unwrap();
let want = format!( let want = format!(
"{}{}\n", "{JUSTFILE}{}\n",
JUSTFILE,
tmp.path().canonicalize().unwrap().display() tmp.path().canonicalize().unwrap().display()
); );

View File

@ -169,8 +169,8 @@ impl Test {
pub(crate) fn write(self, path: impl AsRef<Path>, content: impl AsRef<[u8]>) -> Self { pub(crate) fn write(self, path: impl AsRef<Path>, content: impl AsRef<[u8]>) -> Self {
let path = self.tempdir.path().join(path); let path = self.tempdir.path().join(path);
std::fs::create_dir_all(path.parent().unwrap()).unwrap(); fs::create_dir_all(path.parent().unwrap()).unwrap();
std::fs::write(path, content).unwrap(); fs::write(path, content).unwrap();
self self
} }
} }
@ -224,7 +224,7 @@ impl Test {
fn compare<T: PartialEq + Debug>(name: &str, have: T, want: T) -> bool { fn compare<T: PartialEq + Debug>(name: &str, have: T, want: T) -> bool {
let equal = have == want; let equal = have == want;
if !equal { if !equal {
eprintln!("Bad {}: {}", name, Comparison::new(&have, &want)); eprintln!("Bad {name}: {}", Comparison::new(&have, &want));
} }
equal equal
} }