Only use colors & text decorations on ANSI-capable terminals.
Fixes #404.
This commit is contained in:
parent
2f2be39813
commit
a46a9fca41
|
@ -1488,6 +1488,9 @@ name = "owo-colors"
|
|||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
dependencies = [
|
||||
"supports-color",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pallas"
|
||||
|
|
|
@ -18,7 +18,7 @@ indoc = "1.0.7"
|
|||
itertools = "0.10.5"
|
||||
miette = "5.2.0"
|
||||
ordinal = "0.3.2"
|
||||
owo-colors = "3.5.0"
|
||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||
strum = "0.24.1"
|
||||
thiserror = "1.0.37"
|
||||
uplc = { path = '../uplc', version = "0.0.29" }
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
tipo::{PatternConstructor, Type, TypeInfo},
|
||||
};
|
||||
use miette::Diagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
|
||||
pub const ASSERT_VARIABLE: &str = "_try";
|
||||
pub const CAPTURE_VARIABLE: &str = "_capture";
|
||||
|
@ -1190,8 +1190,8 @@ impl chumsky::Span for Span {
|
|||
pub enum Error {
|
||||
#[error(
|
||||
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
||||
name.purple(),
|
||||
keyword.purple()
|
||||
name.if_supports_color(Stdout, |s| s.purple()),
|
||||
keyword.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
||||
#[diagnostic(code("illegal::module_name"))]
|
||||
|
@ -1200,7 +1200,9 @@ pub enum Error {
|
|||
as, expect, check, const, else, fn, if, is, let, opaque, pub, test, todo, trace, type, use, when"#))]
|
||||
KeywordInModuleName { name: String, keyword: String },
|
||||
|
||||
#[error("I realized you used '{}' as a module name, which is reserved (and not available).\n", name.purple())]
|
||||
#[error("I realized you used '{}' as a module name, which is reserved (and not available).\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("illegal::module_name"))]
|
||||
#[diagnostic(help(r#"Some module names are reserved for internal use. This the case of:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{ast::Span, parser::token::Token};
|
||||
use indoc::formatdoc;
|
||||
use miette::Diagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug, Diagnostic, thiserror::Error)]
|
||||
|
@ -123,8 +123,12 @@ pub enum ErrorKind {
|
|||
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
│ {} my_policy_id {}
|
||||
│ #{}
|
||||
"#
|
||||
, "pub const".bright_blue(), "=".yellow(), "\"f4c9f9c4252d86702c2f4c2e49e6648c7cffe3c8f2b6b7d779788f50\"".bright_purple()}))]
|
||||
"#,
|
||||
"pub const".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||
"=".if_supports_color(Stdout, |s| s.yellow()),
|
||||
"\"f4c9f9c4252d86702c2f4c2e49e6648c7cffe3c8f2b6b7d779788f50\""
|
||||
.if_supports_color(Stdout, |s| s.bright_purple())
|
||||
}))]
|
||||
MalformedBase16StringLiteral,
|
||||
|
||||
#[error("I failed to understand a when clause guard.")]
|
||||
|
@ -143,10 +147,10 @@ pub enum ErrorKind {
|
|||
{bad} (x, _) if x % 3 == 0 -> ...
|
||||
{bad} (x, y) if x + y > 42 -> ...
|
||||
"#
|
||||
, operator_or = "||".yellow()
|
||||
, operator_and = "&&".yellow()
|
||||
, good = "✔️".green()
|
||||
, bad = "✖️".red()
|
||||
, operator_or = "||".if_supports_color(Stdout, |s| s.yellow())
|
||||
, operator_and = "&&".if_supports_color(Stdout, |s| s.yellow())
|
||||
, good = "✔️".if_supports_color(Stdout, |s| s.green())
|
||||
, bad = "✖️".if_supports_color(Stdout, |s| s.red())
|
||||
}))]
|
||||
InvalidWhenClause,
|
||||
}
|
||||
|
|
|
@ -9,7 +9,10 @@ use crate::{
|
|||
use indoc::formatdoc;
|
||||
use miette::{Diagnostic, LabeledSpan};
|
||||
use ordinal::Ordinal;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{
|
||||
OwoColorize,
|
||||
Stream::{Stderr, Stdout},
|
||||
};
|
||||
use std::{collections::HashMap, fmt::Display, sync::Arc};
|
||||
|
||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||
|
@ -37,7 +40,7 @@ impl Diagnostic for UnknownLabels {
|
|||
{known_labels}"#
|
||||
, known_labels = self.valid
|
||||
.iter()
|
||||
.map(|s| format!("─▶ {}", s.yellow()))
|
||||
.map(|s| format!("─▶ {}", s.if_supports_color(Stdout, |s| s.yellow())))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}))
|
||||
|
@ -85,10 +88,14 @@ pub enum Error {
|
|||
errors: Vec<Snippet>,
|
||||
},
|
||||
|
||||
#[error("I found two function arguments both called '{}'.\n", label.purple())]
|
||||
#[error(
|
||||
"I found two function arguments both called '{}'.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("duplicate::argument"))]
|
||||
#[diagnostic(help("Function arguments cannot have the same name. You can use '{discard}' and numbers to distinguish between similar names."
|
||||
, discard = "_".yellow()
|
||||
#[diagnostic(help(
|
||||
"Function arguments cannot have the same name. You can use '{discard}' and numbers to distinguish between similar names.",
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
))]
|
||||
DuplicateArgument {
|
||||
#[label]
|
||||
|
@ -100,8 +107,9 @@ pub enum Error {
|
|||
|
||||
#[error("I found two declarations for the constant '{}'.\n", name.purple())]
|
||||
#[diagnostic(code("duplicate::constant"))]
|
||||
#[diagnostic(help("Top-level constants of a same module cannot have the same name. You can use '{discard}' and numbers to distinguish between similar names."
|
||||
, discard = "_".yellow()
|
||||
#[diagnostic(help(
|
||||
"Top-level constants of a same module cannot have the same name. You can use '{discard}' and numbers to distinguish between similar names.",
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
))]
|
||||
DuplicateConstName {
|
||||
#[label("declared again here")]
|
||||
|
@ -111,7 +119,10 @@ pub enum Error {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I stumbled upon the field '{}' twice in a data-type definition.\n", label.purple())]
|
||||
#[error(
|
||||
"I stumbled upon the field '{}' twice in a data-type definition.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("duplicate::field"))]
|
||||
#[diagnostic(help(r#"Data-types must have fields with strictly different names. You can use '{discard}' and numbers to distinguish between similar names.
|
||||
Note that it is also possible to declare data-types with positional (nameless) fields only.
|
||||
|
@ -123,12 +134,12 @@ For example:
|
|||
│ {variant_Point}({type_Int}, {type_Int}, {type_Int})
|
||||
│ }}
|
||||
"#
|
||||
, discard = "_".yellow()
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
, keyword_type = "type".yellow()
|
||||
, type_Int = "Int".green()
|
||||
, type_Point = "Point".green()
|
||||
, variant_Point = "Point".green()
|
||||
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_type = "type".if_supports_color(Stdout, |s| s.yellow())
|
||||
, type_Int = "Int".if_supports_color(Stdout, |s| s.green())
|
||||
, type_Point = "Point".if_supports_color(Stdout, |s| s.green())
|
||||
, variant_Point = "Point".if_supports_color(Stdout, |s| s.green())
|
||||
))]
|
||||
DuplicateField {
|
||||
#[label]
|
||||
|
@ -138,7 +149,10 @@ For example:
|
|||
label: String,
|
||||
},
|
||||
|
||||
#[error("I noticed you were importing '{}' twice.\n", name.purple())]
|
||||
#[error(
|
||||
"I noticed you were importing '{}' twice.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("duplicate::import"))]
|
||||
#[diagnostic(help(r#"If you're trying to import two modules with identical names but from different packages, you'll need to use a named import.
|
||||
For example:
|
||||
|
@ -146,9 +160,13 @@ For example:
|
|||
╰─▶ {keyword_use} {import} {keyword_as} {named}
|
||||
|
||||
Otherwise, just remove the redundant import."#
|
||||
, keyword_use = "use".bright_blue()
|
||||
, keyword_as = "as".bright_blue()
|
||||
, import = module.iter().map(|x| x.purple().bold().to_string()).collect::<Vec<_>>().join("/".bold().to_string().as_ref())
|
||||
, keyword_use = "use".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_as = "as".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, import = module
|
||||
.iter()
|
||||
.map(|x| x.if_supports_color(Stdout, |s| s.purple()).to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("/".if_supports_color(Stdout, |s| s.bold()).to_string().as_ref())
|
||||
, named = module.join("_")
|
||||
))]
|
||||
DuplicateImport {
|
||||
|
@ -160,13 +178,17 @@ Otherwise, just remove the redundant import."#
|
|||
previous_location: Span,
|
||||
},
|
||||
|
||||
#[error("I discovered two top-level objects referred to as '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered two top-level objects referred to as '{}'.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("duplicate::name"))]
|
||||
#[diagnostic(help(r#"Top-level definitions cannot have the same name, even if they refer to objects with different natures (e.g. function and test).
|
||||
#[diagnostic(help(
|
||||
r#"Top-level definitions cannot have the same name, even if they refer to objects with different natures (e.g. function and test).
|
||||
|
||||
You can use '{discard}' and numbers to distinguish between similar names.
|
||||
"#
|
||||
, discard = "_".yellow()
|
||||
"#,
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
))]
|
||||
DuplicateName {
|
||||
#[label]
|
||||
|
@ -176,10 +198,14 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I found two types declared with the same name: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I found two types declared with the same name: '{}'.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("duplicate::type"))]
|
||||
#[diagnostic(help("Types cannot have the same top-level name. You {cannot} use '_' in types name, but you can use numbers to distinguish between similar names."
|
||||
, cannot = "cannot".red()
|
||||
#[diagnostic(help(
|
||||
"Types cannot have the same top-level name. You {cannot} use '_' in types name, but you can use numbers to distinguish between similar names.",
|
||||
cannot = "cannot".if_supports_color(Stdout, |s| s.red())
|
||||
))]
|
||||
DuplicateTypeName {
|
||||
#[label]
|
||||
|
@ -189,7 +215,10 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I realized the variable '{}' was mentioned more than once in an alternative pattern.\n", name.purple())]
|
||||
#[error(
|
||||
"I realized the variable '{}' was mentioned more than once in an alternative pattern.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url(
|
||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
||||
))]
|
||||
|
@ -200,7 +229,10 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I tripped over an extra variable in an alternative pattern: {}.\n", name.purple())]
|
||||
#[error(
|
||||
"I tripped over an extra variable in an alternative pattern: {}.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url(
|
||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
||||
))]
|
||||
|
@ -221,16 +253,21 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
|||
|
||||
#[error("I found a discarded expression not bound to a variable.\n")]
|
||||
#[diagnostic(code("implicit_discard"))]
|
||||
#[diagnostic(help("A function can contain a sequence of expressions. However, any expression but the last one must be assign to a variable using the {keyword_let} keyword. If you really wish to discard an expression that is unused, you can assign it to '{discard}'."
|
||||
, keyword_let = "let".yellow()
|
||||
, discard = "_".yellow()
|
||||
#[diagnostic(help(
|
||||
"A function can contain a sequence of expressions. However, any expression but the last one must be assign to a variable using the {keyword_let} keyword. If you really wish to discard an expression that is unused, you can assign it to '{discard}'.",
|
||||
keyword_let = "let".if_supports_color(Stdout, |s| s.yellow()),
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
))]
|
||||
ImplicitlyDiscardedExpression {
|
||||
#[label]
|
||||
location: Span,
|
||||
},
|
||||
|
||||
#[error("I saw a {} fields in a context where there should be {}.\n", given.purple(), expected.purple())]
|
||||
#[error(
|
||||
"I saw a {} fields in a context where there should be {}.\n",
|
||||
given.if_supports_color(Stdout, |s| s.purple()),
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/custom-types"))]
|
||||
#[diagnostic(code("arity::constructor"))]
|
||||
IncorrectFieldsArity {
|
||||
|
@ -241,7 +278,11 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
|||
labels: Vec<String>,
|
||||
},
|
||||
|
||||
#[error("I saw a function or constructor that expects {} arguments be called with {} arguments.\n", expected.purple(), given.purple())]
|
||||
#[error(
|
||||
"I saw a function or constructor that expects {} arguments be called with {} arguments.\n",
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
given.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/functions#named-functions"))]
|
||||
#[diagnostic(code("arity::invoke"))]
|
||||
#[diagnostic(help(r#"Functions (and constructors) must always be called with all their arguments (comma-separated, between brackets).
|
||||
|
@ -260,11 +301,11 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
┍━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
│ {keyword_let} increment = add(1, _)
|
||||
"#
|
||||
, discard = "_".yellow()
|
||||
, expected = expected.purple()
|
||||
, keyword_fn = "fn".yellow()
|
||||
, keyword_let = "let".yellow()
|
||||
, type_Int = "Int".green()
|
||||
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
, expected = expected.if_supports_color(Stdout, |s| s.purple())
|
||||
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_let = "let".if_supports_color(Stdout, |s| s.yellow())
|
||||
, type_Int = "Int".if_supports_color(Stdout, |s| s.green())
|
||||
))]
|
||||
IncorrectFunctionCallArity {
|
||||
#[label]
|
||||
|
@ -276,7 +317,11 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
// TODO: Since we do not actually support patterns on multiple items, we won't likely ever
|
||||
// encounter that error. We could simplify a bit the type-checker and get rid of that error
|
||||
// eventually.
|
||||
#[error("I counted {} different clauses in a multi-pattern instead of {}.\n", given.purple(), expected.purple())]
|
||||
#[error(
|
||||
"I counted {} different clauses in a multi-pattern instead of {}.\n",
|
||||
given.if_supports_color(Stdout, |s| s.purple()),
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(code("arity::clause"))]
|
||||
IncorrectNumClausePatterns {
|
||||
#[label]
|
||||
|
@ -285,12 +330,17 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
given: usize,
|
||||
},
|
||||
|
||||
#[error("I saw a pattern on a constructor that has {} field(s) be matched with {} argument(s).\n", expected.purple(), given.len().purple())]
|
||||
#[error(
|
||||
"I saw a pattern on a constructor that has {} field(s) be matched with {} argument(s).\n",
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
given.len().if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#matching"))]
|
||||
#[diagnostic(code("arity::pattern"))]
|
||||
#[diagnostic(help("When pattern-matching on constructors, you must either match the exact number of fields, or use the spread operator '{spread}'. Note that unused fields must be discarded by prefixing their name with '{discard}'."
|
||||
, discard = "_".yellow()
|
||||
, spread = "..".yellow()
|
||||
#[diagnostic(help(
|
||||
"When pattern-matching on constructors, you must either match the exact number of fields, or use the spread operator '{spread}'. Note that unused fields must be discarded by prefixing their name with '{discard}'.",
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow()),
|
||||
spread = "..".if_supports_color(Stdout, |s| s.yellow()),
|
||||
))]
|
||||
IncorrectPatternArity {
|
||||
#[label("{}", suggest_pattern(*expected, name, given, module, *is_record).unwrap_or_default())]
|
||||
|
@ -302,11 +352,16 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
is_record: bool,
|
||||
},
|
||||
|
||||
#[error("I saw a pattern on a {}-tuple be matched into a {}-tuple.\n", expected.purple(), given.purple())]
|
||||
#[error(
|
||||
"I saw a pattern on a {}-tuple be matched into a {}-tuple.\n",
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
given.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#destructuring"))]
|
||||
#[diagnostic(code("arity::tuple"))]
|
||||
#[diagnostic(help("When pattern matching on a tuple, you must match all of its elements. Note that unused fields must be discarded by prefixing their name with '{discard}'."
|
||||
, discard = "_".yellow()
|
||||
#[diagnostic(help(
|
||||
"When pattern matching on a tuple, you must match all of its elements. Note that unused fields must be discarded by prefixing their name with '{discard}'.",
|
||||
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
))]
|
||||
IncorrectTupleArity {
|
||||
#[label]
|
||||
|
@ -315,7 +370,11 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
given: usize,
|
||||
},
|
||||
|
||||
#[error("I noticed a generic data-type with {} type parameters instead of {}.\n", given.purple(), expected.purple())]
|
||||
#[error(
|
||||
"I noticed a generic data-type with {} type parameters instead of {}.\n",
|
||||
given.if_supports_color(Stdout, |s| s.purple()),
|
||||
expected.if_supports_color(Stdout, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/custom-types#generics"))]
|
||||
#[diagnostic(code("arity::generic"))]
|
||||
#[diagnostic(help(r#"Data-types that are generic in one or more types must be written with all their generic types in type annotations. Generic types must be indicated between chevrons '{chevron_left}' and '{chevron_right}'.
|
||||
|
@ -323,8 +382,8 @@ From there, you can define 'increment', a function that takes a single argument
|
|||
Perhaps, try the following:
|
||||
|
||||
╰─▶ {suggestion}"#
|
||||
, chevron_left = "<".yellow()
|
||||
, chevron_right = ">".yellow()
|
||||
, chevron_left = "<".if_supports_color(Stdout, |s| s.yellow())
|
||||
, chevron_right = ">".if_supports_color(Stdout, |s| s.yellow())
|
||||
, suggestion = suggest_generic(name, *expected)
|
||||
))]
|
||||
IncorrectTypeArity {
|
||||
|
@ -337,8 +396,8 @@ Perhaps, try the following:
|
|||
|
||||
#[error(
|
||||
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
||||
name.purple(),
|
||||
keyword.purple()
|
||||
name.if_supports_color(Stdout, |s| s.purple()),
|
||||
keyword.if_supports_color(Stdout, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
||||
#[diagnostic(code("illegal::module_name"))]
|
||||
|
@ -363,7 +422,10 @@ If you really meant to return that last expression, try to replace it with the f
|
|||
expr: expr::UntypedExpr,
|
||||
},
|
||||
|
||||
#[error("I found a missing variable in an alternative pattern: {}.\n", name.purple())]
|
||||
#[error(
|
||||
"I found a missing variable in an alternative pattern: {}.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url(
|
||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
||||
))]
|
||||
|
@ -374,7 +436,10 @@ If you really meant to return that last expression, try to replace it with the f
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I stumbled upon an invalid (non-local) clause guard '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I stumbled upon an invalid (non-local) clause guard '{}'.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/control-flow#checking-equality-and-ordering-in-patterns"))]
|
||||
#[diagnostic(code("illegal::clause_guard"))]
|
||||
#[diagnostic(help("There are some conditions regarding what can be used in a guard. Values must be either local to the function, or defined as module constants. You can't use functions or records in there."))]
|
||||
|
@ -389,10 +454,11 @@ If you really meant to return that last expression, try to replace it with the f
|
|||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||
#[diagnostic(code("illegal::tuple_index"))]
|
||||
#[diagnostic(help(r#"Because you used a tuple-index on an element, I assumed it had to be a tuple or some kind, but instead I found:
|
||||
#[diagnostic(help(
|
||||
r#"Because you used a tuple-index on an element, I assumed it had to be a tuple or some kind, but instead I found:
|
||||
|
||||
╰─▶ {type_info}"#
|
||||
, type_info = tipo.to_pretty(4).red()
|
||||
╰─▶ {type_info}"#,
|
||||
type_info = tipo.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
||||
))]
|
||||
NotATuple {
|
||||
#[label]
|
||||
|
@ -405,8 +471,8 @@ If you really meant to return that last expression, try to replace it with the f
|
|||
} else {
|
||||
format!(
|
||||
"I realized that a given '{keyword_when}/{keyword_is}' expression is non-exhaustive.",
|
||||
keyword_is = "is".purple(),
|
||||
keyword_when = "when".purple()
|
||||
keyword_is = "is".if_supports_color(Stdout, |s| s.purple()),
|
||||
keyword_when = "when".if_supports_color(Stdout, |s| s.purple())
|
||||
)
|
||||
}
|
||||
)]
|
||||
|
@ -417,9 +483,9 @@ If you really meant to return that last expression, try to replace it with the f
|
|||
In this particular instance, the following cases are unmatched:
|
||||
|
||||
{missing}"#
|
||||
, discard = "_".yellow()
|
||||
, keyword_is = "is".purple()
|
||||
, keyword_when = "when".purple()
|
||||
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_is = "is".if_supports_color(Stdout, |s| s.purple())
|
||||
, keyword_when = "when".if_supports_color(Stdout, |s| s.purple())
|
||||
, missing = unmatched
|
||||
.iter()
|
||||
.map(|s| format!("─▶ {s}"))
|
||||
|
@ -435,10 +501,11 @@ In this particular instance, the following cases are unmatched:
|
|||
|
||||
#[error("I tripped over a call attempt on something that isn't a function.\n")]
|
||||
#[diagnostic(code("illegal::invoke"))]
|
||||
#[diagnostic(help(r#"It seems like you're trying to call something that isn't a function. I am inferring the following type:
|
||||
#[diagnostic(help(
|
||||
r#"It seems like you're trying to call something that isn't a function. I am inferring the following type:
|
||||
|
||||
╰─▶ {inference}"#
|
||||
, inference = tipo.to_pretty(4)
|
||||
╰─▶ {inference}"#,
|
||||
inference = tipo.to_pretty(0)
|
||||
))]
|
||||
NotFn {
|
||||
#[label]
|
||||
|
@ -468,8 +535,8 @@ The culprit is:
|
|||
{type_info}
|
||||
|
||||
Maybe you meant to turn it public using the '{keyword_pub}' keyword?"#
|
||||
, type_info = leaked.to_pretty(4).red()
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
, type_info = leaked.to_pretty(4).if_supports_color(Stdout, |s| s.red())
|
||||
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
))]
|
||||
PrivateTypeLeak {
|
||||
#[label]
|
||||
|
@ -495,9 +562,9 @@ You can help me by providing a type-annotation for 'x', as such:
|
|||
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
│ {keyword_let} foo = {keyword_fn}(x: {type_ScriptContext}) {{ x.transaction }}
|
||||
"#
|
||||
, keyword_fn = "fn".yellow()
|
||||
, keyword_let = "let".yellow()
|
||||
, type_ScriptContext = "ScriptContext".green()
|
||||
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_let = "let".if_supports_color(Stdout, |s| s.yellow())
|
||||
, type_ScriptContext = "ScriptContext".if_supports_color(Stdout, |s| s.green())
|
||||
))]
|
||||
RecordAccessUnknownType {
|
||||
#[label]
|
||||
|
@ -523,8 +590,8 @@ You can help me by providing a type-annotation for 'x', as such:
|
|||
|
||||
#[error(
|
||||
"I discovered an attempt to access the {} element of a {}-tuple.\n",
|
||||
Ordinal(*index + 1).to_string().purple(),
|
||||
size.purple()
|
||||
Ordinal(*index + 1).to_string().if_supports_color(Stdout, |s| s.purple()),
|
||||
size.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||
#[diagnostic(code("invalid::tuple_index"))]
|
||||
|
@ -535,7 +602,10 @@ You can help me by providing a type-annotation for 'x', as such:
|
|||
size: usize,
|
||||
},
|
||||
|
||||
#[error("I tripped over the following labeled argument: {}.\n", label.purple())]
|
||||
#[error(
|
||||
"I tripped over the following labeled argument: {}.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/functions#labeled-arguments"))]
|
||||
#[diagnostic(code("unexpected::module_name"))]
|
||||
UnexpectedLabeledArg {
|
||||
|
@ -544,7 +614,10 @@ You can help me by providing a type-annotation for 'x', as such:
|
|||
label: String,
|
||||
},
|
||||
|
||||
#[error("I tripped over the following labeled argument: {}.\n", label.purple())]
|
||||
#[error(
|
||||
"I tripped over the following labeled argument: {}.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/custom-types#named-accessors"))]
|
||||
#[diagnostic(code("unexpected::labeled_argument"))]
|
||||
#[diagnostic(help(r#"The constructor '{constructor}' does not have any labeled field. Its fields must therefore be matched only by position.
|
||||
|
@ -553,7 +626,9 @@ Perhaps, try the following:
|
|||
|
||||
╰─▶ {suggestion}
|
||||
"#
|
||||
, constructor = name.green()
|
||||
, constructor = name
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
, suggestion = suggest_constructor_pattern(name, args, module, *with_spread)
|
||||
))]
|
||||
UnexpectedLabeledArgInPattern {
|
||||
|
@ -579,7 +654,10 @@ Perhaps, try the following:
|
|||
#[diagnostic(code("unknown::labels"))]
|
||||
UnknownLabels(#[related] Vec<UnknownLabels>),
|
||||
|
||||
#[error("I stumbled upon a reference to an unknown module: '{}'\n", name.purple())]
|
||||
#[error(
|
||||
"I stumbled upon a reference to an unknown module: '{}'\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unknown::module"))]
|
||||
#[diagnostic(help(
|
||||
"{}",
|
||||
|
@ -594,8 +672,8 @@ Perhaps, try the following:
|
|||
|
||||
#[error(
|
||||
"I found an unknown import '{}' from module '{}'.\n",
|
||||
name.purple(),
|
||||
module_name.purple()
|
||||
name.if_supports_color(Stdout, |s| s.purple()),
|
||||
module_name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unknown::module_field"))]
|
||||
#[diagnostic(help(
|
||||
|
@ -615,7 +693,11 @@ Perhaps, try the following:
|
|||
type_constructors: Vec<String>,
|
||||
},
|
||||
|
||||
#[error("I looked for '{}' in '{}' but couldn't find it.\n", name.purple(), module_name.purple())]
|
||||
#[error(
|
||||
"I looked for '{}' in '{}' but couldn't find it.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple()),
|
||||
module_name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unknown::module_type"))]
|
||||
#[diagnostic(help(
|
||||
"{}",
|
||||
|
@ -633,7 +715,10 @@ Perhaps, try the following:
|
|||
type_constructors: Vec<String>,
|
||||
},
|
||||
|
||||
#[error("I looked for '{}' in '{}' but couldn't find it.\n", name.purple(), module_name.purple())]
|
||||
#[error("I looked for '{}' in '{}' but couldn't find it.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple()),
|
||||
module_name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unknown::module_value"))]
|
||||
#[diagnostic(help(
|
||||
"{}",
|
||||
|
@ -652,14 +737,14 @@ Perhaps, try the following:
|
|||
},
|
||||
|
||||
#[error(
|
||||
"I looked for the field '{}' in a record of type '{}' couldn't find it.\n",
|
||||
label.purple(),
|
||||
typ.to_pretty(4).purple()
|
||||
"I looked for the field '{}' in a record of type '{}' but couldn't find it.\n",
|
||||
label.if_supports_color(Stdout, |s| s.purple()),
|
||||
typ.to_pretty(0).if_supports_color(Stdout, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(code("unknown::record_field"))]
|
||||
#[diagnostic(help(
|
||||
"{}",
|
||||
suggest_neighbor(label, fields.iter(), "Did you forget to make the it public?")
|
||||
suggest_neighbor(label, fields.iter(), "Did you forget to make it public?")
|
||||
))]
|
||||
UnknownRecordField {
|
||||
#[label]
|
||||
|
@ -683,7 +768,10 @@ Perhaps, try the following:
|
|||
types: Vec<String>,
|
||||
},
|
||||
|
||||
#[error("I found a reference to an unknown data-type constructor: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I found a reference to an unknown data-type constructor: '{}'.\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unknown::type_constructor"))]
|
||||
#[diagnostic(help(
|
||||
"{}",
|
||||
|
@ -737,24 +825,37 @@ The best thing to do from here is to remove it."#))]
|
|||
location: Span,
|
||||
},
|
||||
|
||||
#[error("I discovered an attempt to import a validator module: '{}'\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered an attempt to import a validator module: '{}'\n",
|
||||
name.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("illegal::import"))]
|
||||
#[diagnostic(help("If you are trying to share code defined in a validator then move it to a library module under {}", "lib/".purple()))]
|
||||
#[diagnostic(help(
|
||||
"If you are trying to share code defined in a validator then move it to a library module under {}",
|
||||
"lib/".if_supports_color(Stdout, |s| s.purple()))
|
||||
)]
|
||||
ValidatorImported {
|
||||
#[label]
|
||||
location: Span,
|
||||
name: String,
|
||||
},
|
||||
|
||||
#[error("A validator must return {}", "Bool".bright_blue().bold())]
|
||||
#[error(
|
||||
"A validator must return {}",
|
||||
"Bool"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
)]
|
||||
#[diagnostic(code("illegal::validator_return_type"))]
|
||||
#[diagnostic(help(r#"While analyzing the return type of your validator, I found it to be:
|
||||
|
||||
╰─▶ {signature}
|
||||
|
||||
...but I expected this to be a {type_Bool}. If I am inferring the wrong type, try annotating the validator's return type with Bool"#
|
||||
, type_Bool = "Bool".bright_blue().bold()
|
||||
, signature = return_type.to_pretty(0).red()
|
||||
, type_Bool = "Bool"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
, signature = return_type.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
||||
))]
|
||||
ValidatorMustReturnBool {
|
||||
#[label("invalid return type")]
|
||||
|
@ -775,7 +876,10 @@ The best thing to do from here is to remove it."#))]
|
|||
arguments.push('s');
|
||||
}
|
||||
|
||||
format!("please add the {} missing {arguments}", missing.to_string().yellow())
|
||||
format!(
|
||||
"please add the {} missing {arguments}",
|
||||
missing.to_string().if_supports_color(Stdout, |s| s.yellow()),
|
||||
)
|
||||
} else {
|
||||
let extra = count - 3;
|
||||
|
||||
|
@ -785,7 +889,10 @@ The best thing to do from here is to remove it."#))]
|
|||
arguments.push('s');
|
||||
}
|
||||
|
||||
format!("please remove the {} extra {arguments}", extra.to_string().yellow())
|
||||
format!(
|
||||
"please remove the {} extra {arguments}",
|
||||
extra.to_string().if_supports_color(Stdout, |s| s.yellow()),
|
||||
)
|
||||
}
|
||||
))]
|
||||
IncorrectValidatorArity {
|
||||
|
@ -881,7 +988,10 @@ fn suggest_neighbor<'a>(
|
|||
.min_by(|(_, a), (_, b)| a.cmp(b))
|
||||
.and_then(|(suggestion, distance)| {
|
||||
if distance <= threshold {
|
||||
Some(format!("Did you mean '{}'?", suggestion.yellow()))
|
||||
Some(format!(
|
||||
"Did you mean '{}'?",
|
||||
suggestion.if_supports_color(Stdout, |s| s.yellow())
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -962,10 +1072,10 @@ fn suggest_unify(
|
|||
{given}
|
||||
|
||||
Note that I infer the type of the entire '{keyword_when}/{keyword_is}' expression based on the type of the first branch I encounter."#,
|
||||
keyword_when = "when".yellow(),
|
||||
keyword_is = "is".yellow(),
|
||||
expected = expected.green(),
|
||||
given = given.red()
|
||||
keyword_when = "when".if_supports_color(Stdout, |s| s.yellow()),
|
||||
keyword_is = "is".if_supports_color(Stdout, |s| s.yellow()),
|
||||
expected = expected.if_supports_color(Stdout, |s| s.green()),
|
||||
given = given.if_supports_color(Stdout, |s| s.red())
|
||||
},
|
||||
Some(UnifyErrorSituation::ReturnAnnotationMismatch) => formatdoc! {
|
||||
r#"While comparing the return annotation of a function with its actual return type, I realized that both don't match.
|
||||
|
@ -979,8 +1089,8 @@ fn suggest_unify(
|
|||
{}
|
||||
|
||||
Either, fix the annotation or adjust the function body to return the expected type."#,
|
||||
expected.green(),
|
||||
given.red()
|
||||
expected.if_supports_color(Stdout, |s| s.green()),
|
||||
given.if_supports_color(Stdout, |s| s.red())
|
||||
},
|
||||
Some(UnifyErrorSituation::PipeTypeMismatch) => formatdoc! {
|
||||
r#"As I was looking at a pipeline you have defined, I realized that one of the pipe isn't valid.
|
||||
|
@ -994,8 +1104,8 @@ fn suggest_unify(
|
|||
{}
|
||||
|
||||
Either, fix the input or change the target so that both match."#,
|
||||
expected.green(),
|
||||
given.red()
|
||||
expected.if_supports_color(Stdout, |s| s.green()),
|
||||
given.if_supports_color(Stdout, |s| s.red())
|
||||
},
|
||||
Some(UnifyErrorSituation::Operator(op)) => formatdoc! {
|
||||
r#"While checking operands of a binary operator, I realized that at least one of them doesn't have the expected type.
|
||||
|
@ -1008,9 +1118,9 @@ fn suggest_unify(
|
|||
|
||||
{}
|
||||
"#,
|
||||
op.to_doc().to_pretty_string(70).yellow(),
|
||||
expected.green(),
|
||||
given.red()
|
||||
op.to_doc().to_pretty_string(70).if_supports_color(Stdout, |s| s.yellow()),
|
||||
expected.if_supports_color(Stdout, |s| s.green()),
|
||||
given.if_supports_color(Stdout, |s| s.red())
|
||||
},
|
||||
None => formatdoc! {
|
||||
r#"I am inferring the following type:
|
||||
|
@ -1022,8 +1132,8 @@ fn suggest_unify(
|
|||
{}
|
||||
|
||||
Either, add type-annotation to improve my inference, or adjust the expression to have the expected type."#,
|
||||
expected.green(),
|
||||
given.red()
|
||||
expected.if_supports_color(Stdout, |s| s.green()),
|
||||
given.if_supports_color(Stdout, |s| s.red())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1044,12 +1154,16 @@ fn suggest_make_public() -> String {
|
|||
|
||||
The function 'foo' is private and can't be accessed from outside of the 'aiken/foo' module. But the data-type '{type_Bar}' is public and available.
|
||||
"#
|
||||
, keyword_fn = "fn".yellow()
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
, keyword_type = "type".yellow()
|
||||
, literal_foo = "\"foo\"".bright_purple()
|
||||
, type_Bar = "Bar".green()
|
||||
, variant_Bar = "Bar".green()
|
||||
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_type = "type".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, literal_foo = "\"foo\"".if_supports_color(Stdout, |s| s.bright_purple())
|
||||
, type_Bar = "Bar"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
, variant_Bar = "Bar"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,15 +1191,21 @@ fn suggest_import_constructor() -> String {
|
|||
│ }}
|
||||
│ }}
|
||||
"#
|
||||
, keyword_fn = "fn".yellow()
|
||||
, keyword_is = "is".yellow()
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
, keyword_type = "type".yellow()
|
||||
, keyword_use = "use".bright_blue()
|
||||
, keyword_when = "when".yellow()
|
||||
, type_Pet = "Pet".green()
|
||||
, variant_Cat = "Cat".green()
|
||||
, variant_Dog = "Dog".green()
|
||||
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_is = "is".if_supports_color(Stdout, |s| s.yellow())
|
||||
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_type = "type".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_use = "use".if_supports_color(Stdout, |s| s.bright_blue())
|
||||
, keyword_when = "when".if_supports_color(Stdout, |s| s.yellow())
|
||||
, type_Pet = "Pet"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
, variant_Cat = "Cat"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
, variant_Dog = "Dog"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,7 +1249,11 @@ pub enum Warning {
|
|||
#[error("I found a when expression with a single clause.")]
|
||||
#[diagnostic(
|
||||
code("single_when_clause"),
|
||||
help("Prefer using a {} binding like so...\n\n{}", "let".purple(), format_suggestion(sample))
|
||||
help(
|
||||
"Prefer using a {} binding like so...\n\n{}",
|
||||
"let".if_supports_color(Stderr, |s| s.purple()),
|
||||
format_suggestion(sample)
|
||||
)
|
||||
)]
|
||||
SingleWhenClause {
|
||||
#[label("use let")]
|
||||
|
@ -1137,10 +1261,19 @@ pub enum Warning {
|
|||
sample: UntypedExpr,
|
||||
},
|
||||
|
||||
#[error("I found an {} trying to match a type with one constructor", "expect".purple())]
|
||||
#[error(
|
||||
"I found an {} trying to match a type with one constructor",
|
||||
"expect".if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(
|
||||
code("single_constructor_expect"),
|
||||
help("If your type has one constructor, unless you are casting {} {}, you can\nprefer using a {} binding like so...\n\n{}", "FROM".bold(), "Data".purple(), "let".purple(), format_suggestion(sample))
|
||||
help(
|
||||
"If your type has one constructor, unless you are casting {} {}, you can\nprefer using a {} binding like so...\n\n{}",
|
||||
"from".if_supports_color(Stderr, |s| s.bold()),
|
||||
"Data".if_supports_color(Stderr, |s| s.purple()),
|
||||
"let".if_supports_color(Stderr, |s| s.purple()),
|
||||
format_suggestion(sample)
|
||||
)
|
||||
)]
|
||||
SingleConstructorExpect {
|
||||
#[label("use let")]
|
||||
|
@ -1161,7 +1294,10 @@ pub enum Warning {
|
|||
tipo: Arc<Type>,
|
||||
},
|
||||
|
||||
#[error("I discovered an unused constructor: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered an unused constructor: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"No big deal, but you might want to remove it to get rid of that warning."
|
||||
))]
|
||||
|
@ -1173,7 +1309,10 @@ pub enum Warning {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I discovered an unused imported module: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered an unused imported module: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"No big deal, but you might want to remove it to get rid of that warning."
|
||||
))]
|
||||
|
@ -1184,7 +1323,10 @@ pub enum Warning {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I discovered an unused imported value: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered an unused imported value: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"No big deal, but you might want to remove it to get rid of that warning."
|
||||
))]
|
||||
|
@ -1202,11 +1344,14 @@ pub enum Warning {
|
|||
location: Span,
|
||||
},
|
||||
|
||||
#[error("I found an unused private function: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I found an unused private function: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple()),
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
||||
Otherwise, you might want to get rid of it altogether."
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
Otherwise, you might want to get rid of it altogether.",
|
||||
keyword_pub = "pub".if_supports_color(Stderr, |s| s.bright_blue())
|
||||
))]
|
||||
#[diagnostic(code("unused::function"))]
|
||||
UnusedPrivateFunction {
|
||||
|
@ -1215,11 +1360,14 @@ pub enum Warning {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I found an unused (private) module constant: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I found an unused (private) module constant: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
||||
Otherwise, you might want to get rid of it altogether."
|
||||
, keyword_pub = "pub".bright_blue()
|
||||
Otherwise, you might want to get rid of it altogether.",
|
||||
keyword_pub = "pub".if_supports_color(Stderr, |s| s.bright_blue())
|
||||
))]
|
||||
#[diagnostic(code("unused::constant"))]
|
||||
UnusedPrivateModuleConstant {
|
||||
|
@ -1228,7 +1376,10 @@ pub enum Warning {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I discovered an unused type: '{}'.\n", name.purple())]
|
||||
#[error(
|
||||
"I discovered an unused type: '{}'.\n",
|
||||
name.if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("unused::type"))]
|
||||
UnusedType {
|
||||
#[label]
|
||||
|
@ -1248,10 +1399,13 @@ pub enum Warning {
|
|||
name: String,
|
||||
},
|
||||
|
||||
#[error("I came across a validator in a {} module which means\nI'm going to ignore it.\n", "lib/".purple())]
|
||||
#[error(
|
||||
"I came across a validator in a {} module which means\nI'm going to ignore it.\n",
|
||||
"lib/".if_supports_color(Stderr, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(help(
|
||||
"No big deal, but you might want to move it to a {} module\nor remove it to get rid of that warning.",
|
||||
"validators/".purple()
|
||||
"validators/".if_supports_color(Stderr, |s| s.purple())
|
||||
))]
|
||||
#[diagnostic(code("unused::validator"))]
|
||||
ValidatorInLibraryModule {
|
||||
|
@ -1261,7 +1415,9 @@ pub enum Warning {
|
|||
|
||||
#[error(
|
||||
"I noticed a suspicious {type_ByteArray} UTF-8 literal which resembles a hash digest.",
|
||||
type_ByteArray = "ByteArray".bold().bright_blue()
|
||||
type_ByteArray = "ByteArray"
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
)]
|
||||
#[diagnostic(help("{}", formatdoc! {
|
||||
r#"When you specify a {type_ByteArray} literal using plain double-quotes, it's interpreted as an array of UTF-8 bytes. For example, the literal {literal_foo} is interpreted as the byte sequence {foo_bytes}.
|
||||
|
@ -1270,11 +1426,13 @@ pub enum Warning {
|
|||
|
||||
╰─▶ {symbol_hash}{value}
|
||||
"#,
|
||||
type_ByteArray = "ByteArray".bold().bright_blue(),
|
||||
literal_foo = "\"foo\"".purple(),
|
||||
foo_bytes = "#[102, 111, 111]".purple(),
|
||||
value = "\"{value}\"".purple(),
|
||||
symbol_hash = "#".purple(),
|
||||
type_ByteArray = "ByteArray"
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
literal_foo = "\"foo\"".if_supports_color(Stderr, |s| s.purple()),
|
||||
foo_bytes = "#[102, 111, 111]".if_supports_color(Stderr, |s| s.purple()),
|
||||
value = "\"{value}\"".if_supports_color(Stderr, |s| s.purple()),
|
||||
symbol_hash = "#".if_supports_color(Stderr, |s| s.purple()),
|
||||
}))]
|
||||
#[diagnostic(code("syntax::bytearray_literal_is_hex_string"))]
|
||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#bytearray"))]
|
||||
|
@ -1314,9 +1472,11 @@ fn format_suggestion(sample: &UntypedExpr) -> String {
|
|||
.enumerate()
|
||||
.map(|(ix, line)| {
|
||||
if ix == 0 {
|
||||
format!("╰─▶ {}", line.yellow())
|
||||
format!("╰─▶ {}", line.if_supports_color(Stdout, |s| s.yellow()))
|
||||
} else {
|
||||
format!(" {line}").yellow().to_string()
|
||||
format!(" {line}")
|
||||
.if_supports_color(Stdout, |s| s.yellow())
|
||||
.to_string()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
|
|
@ -20,7 +20,7 @@ ignore = "0.4.18"
|
|||
indexmap = "1.9.1"
|
||||
itertools = "0.10.1"
|
||||
miette = { version = "5.3.0", features = ["fancy"] }
|
||||
owo-colors = "3.5.0"
|
||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||
pallas = "0.16.0"
|
||||
pallas-traverse = "0.16.0"
|
||||
petgraph = "0.6.2"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::schema;
|
||||
use aiken_lang::ast::Span;
|
||||
use miette::{Diagnostic, NamedSource};
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||
|
@ -19,15 +19,25 @@ pub enum Error {
|
|||
|
||||
#[error("Invalid or missing project's blueprint file.")]
|
||||
#[diagnostic(code("aiken::blueprint::missing"))]
|
||||
#[diagnostic(help("Did you forget to {build} the project?", build = "build".purple().bold()))]
|
||||
#[diagnostic(help(
|
||||
"Did you forget to {build} the project?",
|
||||
build = "build"
|
||||
.if_supports_color(Stdout, |s| s.purple())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
))]
|
||||
InvalidOrMissingFile,
|
||||
|
||||
#[error("I didn't find any parameters to apply in the given validator.")]
|
||||
#[diagnostic(code("aiken::blueprint::apply::no_parameters"))]
|
||||
NoParametersToApply,
|
||||
|
||||
#[error("I couldn't compute the address of the given validator because it's parameterized by {} parameter(s)!", format!("{n}").purple())]
|
||||
#[error(
|
||||
"I couldn't compute the address of the given validator because it's parameterized by {} parameter(s)!",
|
||||
n.if_supports_color(Stdout, |s| s.purple())
|
||||
)]
|
||||
#[diagnostic(code("aiken::blueprint::address::parameterized"))]
|
||||
#[diagnostic(help("I can only compute addresses of validators that are fully applied. For example, a {keyword_spend} validator must have exactly 3 arguments: a datum, a redeemer and a context. If it has more, they need to be provided beforehand and applied directly in the validator. Applying parameters change the validator's compiled code, and thus the address.\n\nThis is why I need you to apply parmeters first.", keyword_spend = "spend".purple()))]
|
||||
#[diagnostic(help(
|
||||
"I can only compute addresses of validators that are fully applied. For example, a {keyword_spend} validator must have exactly 3 arguments: a datum, a redeemer and a context. If it has more, they need to be provided beforehand and applied directly in the validator. Applying parameters change the validator's compiled code, and thus the address.\n\nThis is why I need you to apply parmeters first.",
|
||||
keyword_spend = "spend".if_supports_color(Stdout, |s| s.purple())))]
|
||||
ParameterizedValidator { n: usize },
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use aiken_lang::{
|
|||
ast::{DataType, Definition, TypedDefinition},
|
||||
tipo::{pretty, Type, TypeVar},
|
||||
};
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
use serde::{
|
||||
self,
|
||||
ser::{Serialize, SerializeStruct, Serializer},
|
||||
|
@ -533,7 +533,9 @@ I got there when trying to generate a blueprint specification of the following t
|
|||
r#"There cannot be any unbound type variable at the contract's boundary (i.e. in types used as datum and/or redeemer). Indeed, in order to generate an outward-facing specification of the contract's interface, I need to know what concrete representations will the datum and/or the redeemer have.
|
||||
|
||||
If your contract doesn't need datum or redeemer, you can always give them the type {type_Void} to indicate this. It is very concrete and will help me progress forward."#,
|
||||
type_Void = "Void".bright_blue().bold()
|
||||
type_Void = "Void"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
),
|
||||
|
||||
ErrorContext::ExpectedData => format!(
|
||||
|
@ -542,7 +544,9 @@ If your contract doesn't need datum or redeemer, you can always give them the ty
|
|||
There are few restrictions like this one. In this instance, here's the types I followed and that led me to this problem:
|
||||
|
||||
╰─▶ {breadcrumbs}"#,
|
||||
type_String = "String".bright_blue().bold(),
|
||||
type_String = "String"
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold()),
|
||||
breadcrumbs = Error::fmt_breadcrumbs(&self.breadcrumbs)
|
||||
),
|
||||
|
||||
|
@ -564,8 +568,8 @@ Here's the types I followed and that led me to this problem:
|
|||
pretty::Printer::new()
|
||||
.print(type_info)
|
||||
.to_pretty_string(70)
|
||||
.bright_blue()
|
||||
.bold()
|
||||
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||
.if_supports_color(Stdout, |s| s.bold())
|
||||
.to_string()
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
|
|
@ -10,7 +10,7 @@ use aiken_lang::{
|
|||
use miette::{
|
||||
Diagnostic, EyreContext, LabeledSpan, MietteHandlerOpts, NamedSource, RgbColors, SourceCode,
|
||||
};
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
use std::{
|
||||
fmt::{Debug, Display},
|
||||
io,
|
||||
|
@ -121,7 +121,7 @@ pub enum Error {
|
|||
|
||||
impl Error {
|
||||
pub fn report(&self) {
|
||||
eprintln!("Error: {self:?}")
|
||||
println!("{self:?}")
|
||||
}
|
||||
|
||||
pub fn from_parse_errors(errs: Vec<ParseError>, path: &Path, src: &str) -> Vec<Self> {
|
||||
|
@ -314,13 +314,27 @@ impl Diagnostic for Error {
|
|||
Error::NoValidatorNotFound { known_validators } => {
|
||||
Some(Box::new(format!(
|
||||
"Here's a list of all validators I've found in your project. Please double-check this list against the options that you've provided:\n\n{}",
|
||||
known_validators.iter().map(|title| format!("→ {title}", title = title.purple().bold())).collect::<Vec<String>>().join("\n")
|
||||
known_validators
|
||||
.iter()
|
||||
.map(|title| format!(
|
||||
"→ {title}",
|
||||
title = title.if_supports_color(Stdout, |s| s.purple())
|
||||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)))
|
||||
},
|
||||
Error::MoreThanOneValidatorFound { known_validators } => {
|
||||
Some(Box::new(format!(
|
||||
"Here's a list of all validators I've found in your project. Select one of them using the appropriate options:\n\n{}",
|
||||
known_validators.iter().map(|title| format!("→ {title}", title = title.purple().bold())).collect::<Vec<String>>().join("\n")
|
||||
known_validators
|
||||
.iter()
|
||||
.map(|title| format!(
|
||||
"→ {title}",
|
||||
title = title.if_supports_color(Stdout, |s| s.purple())
|
||||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
)))
|
||||
},
|
||||
Error::Module(e) => e.help(),
|
||||
|
@ -526,7 +540,7 @@ impl Warning {
|
|||
}
|
||||
|
||||
pub fn report(&self) {
|
||||
eprintln!("Warning: {self:?}")
|
||||
eprintln!("{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||
use serde::{de::Visitor, Deserialize, Serialize};
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
|
@ -109,12 +109,19 @@ impl<'de> Deserialize<'de> for PackageName {
|
|||
|
||||
#[derive(Debug, Error, miette::Diagnostic)]
|
||||
pub enum Error {
|
||||
#[error("{} is not a valid project name: {}", name.red(), reason.to_string())]
|
||||
#[error(
|
||||
"{} is not a valid project name: {}",
|
||||
name.if_supports_color(Stdout, |s| s.red()),
|
||||
reason.to_string()
|
||||
)]
|
||||
InvalidProjectName {
|
||||
name: String,
|
||||
reason: InvalidProjectNameReason,
|
||||
},
|
||||
#[error("A project named {} already exists.", name.red())]
|
||||
#[error(
|
||||
"A project named {} already exists.",
|
||||
name.if_supports_color(Stdout, |s| s.red())
|
||||
)]
|
||||
ProjectExists { name: String },
|
||||
}
|
||||
|
||||
|
@ -134,9 +141,9 @@ impl fmt::Display for InvalidProjectNameReason {
|
|||
{}/{}\n\nEach part must start with a lowercase letter \
|
||||
and may only contain lowercase letters, numbers, hyphens or underscores.\
|
||||
\nFor example,\n\n\t{}",
|
||||
"{owner}".bright_blue(),
|
||||
"{project}".bright_blue(),
|
||||
"aiken-lang/stdlib".bright_blue(),
|
||||
"{owner}".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||
"{project}".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||
"aiken-lang/stdlib".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ hex = "0.4.3"
|
|||
ignore = "0.4.18"
|
||||
indoc = "1.0"
|
||||
miette = { version = "5.3.0", features = ["fancy"] }
|
||||
owo-colors = "3.5.0"
|
||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||
pallas-addresses = "0.16.0"
|
||||
pallas-codec = "0.16.0"
|
||||
pallas-crypto = "0.16.0"
|
||||
|
|
|
@ -4,7 +4,7 @@ use aiken_project::{
|
|||
};
|
||||
use indoc::{formatdoc, indoc};
|
||||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
|
@ -55,7 +55,7 @@ fn create_project(args: Args, package_name: &PackageName) -> miette::Result<()>
|
|||
}
|
||||
|
||||
fn print_success_message(package_name: &PackageName) {
|
||||
println!(
|
||||
eprintln!(
|
||||
"\n{}",
|
||||
formatdoc! {
|
||||
r#"Your Aiken project {name} has been {s} created.
|
||||
|
@ -64,10 +64,17 @@ fn print_success_message(package_name: &PackageName) {
|
|||
{cd} {name}
|
||||
{aiken} check
|
||||
"#,
|
||||
s = "successfully".bold().bright_green(),
|
||||
cd = "cd".bold().purple(),
|
||||
name = package_name.repo.bright_blue(),
|
||||
aiken = "aiken".bold().purple(),
|
||||
s = "successfully"
|
||||
.if_supports_color(Stderr, |s| s.bright_green())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
cd = "cd"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
name = package_name
|
||||
.if_supports_color(Stderr, |s| s.repo.bright_blue()),
|
||||
aiken = "aiken"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use aiken_project::{
|
|||
pretty,
|
||||
};
|
||||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||
use std::{path::PathBuf, process, str::FromStr};
|
||||
|
||||
#[derive(clap::Args)]
|
||||
|
@ -43,27 +43,29 @@ pub fn exec(args: Args) -> miette::Result<()> {
|
|||
}
|
||||
};
|
||||
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
pretty::pad_left("Package".to_string(), 13, " ")
|
||||
.bold()
|
||||
.purple(),
|
||||
dependency.name.bright_blue(),
|
||||
dependency
|
||||
.name
|
||||
.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||
);
|
||||
|
||||
match config.insert(&dependency, args.overwrite) {
|
||||
Some(config) => {
|
||||
config.save(&root).into_diagnostic()?;
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} version → {}",
|
||||
pretty::pad_left(
|
||||
if args.overwrite { "Changed" } else { "Added" }.to_string(),
|
||||
13,
|
||||
" "
|
||||
)
|
||||
.bold()
|
||||
.purple(),
|
||||
dependency.version.yellow()
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
dependency.version.if_supports_color(Stderr, |s| s.yellow())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
use aiken_project::{paths, pretty};
|
||||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||
use std::fs;
|
||||
|
||||
pub fn exec() -> miette::Result<()> {
|
||||
let dir = paths::packages_cache();
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
pretty::pad_left("Clearing".to_string(), 13, " ")
|
||||
.bold()
|
||||
.purple(),
|
||||
dir.display().bold(),
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
dir.display().if_supports_color(Stderr, |s| s.bold()),
|
||||
);
|
||||
let packages = fs::read_dir(&dir).into_diagnostic()?;
|
||||
for package in packages {
|
||||
let path = package.into_diagnostic()?.path();
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
pretty::pad_left("Removing".to_string(), 13, " ")
|
||||
.bold()
|
||||
.purple(),
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
path.file_name()
|
||||
.unwrap_or_default()
|
||||
.to_str()
|
||||
.unwrap_or_default()
|
||||
.bright_blue(),
|
||||
.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||
);
|
||||
fs::remove_file(path).into_diagnostic()?;
|
||||
}
|
||||
println!(
|
||||
"{}",
|
||||
pretty::pad_left("Done".to_string(), 13, " ")
|
||||
.bold()
|
||||
.purple()
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||
use pallas_primitives::{
|
||||
babbage::{Redeemer, TransactionInput, TransactionOutput},
|
||||
Fragment,
|
||||
|
@ -54,7 +54,12 @@ pub fn exec(
|
|||
zero_slot,
|
||||
}: Args,
|
||||
) -> miette::Result<()> {
|
||||
eprintln!("{} script context", " Parsing".bold().purple(),);
|
||||
eprintln!(
|
||||
"{} script context",
|
||||
" Parsing"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
|
||||
let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor {
|
||||
(
|
||||
|
@ -78,7 +83,13 @@ pub fn exec(
|
|||
.or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))
|
||||
.into_diagnostic()?;
|
||||
|
||||
eprintln!("{} {}", " Simulating".bold().purple(), tx.hash());
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
" Simulating"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
tx.hash()
|
||||
);
|
||||
|
||||
let inputs = Vec::<TransactionInput>::decode_fragment(&inputs_bytes).unwrap();
|
||||
let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap();
|
||||
|
@ -100,9 +111,11 @@ pub fn exec(
|
|||
};
|
||||
|
||||
let with_redeemer = |redeemer: &Redeemer| {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {:?} → {}",
|
||||
" Redeemer".bold().purple(),
|
||||
" Redeemer"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
redeemer.tag,
|
||||
redeemer.index
|
||||
)
|
||||
|
@ -147,7 +160,13 @@ pub fn exec(
|
|||
}
|
||||
|
||||
fn display_tx_error(err: &tx::error::Error) -> String {
|
||||
let mut msg = format!("{} {}", " Error".bold().red(), err.red());
|
||||
let mut msg = format!(
|
||||
"{} {}",
|
||||
" Error"
|
||||
.if_supports_color(Stderr, |s| s.red())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
err.red()
|
||||
);
|
||||
match err {
|
||||
tx::error::Error::RedeemerError { err, .. } => {
|
||||
msg.push_str(&format!(
|
||||
|
@ -164,7 +183,15 @@ fn display_tx_error(err: &tx::error::Error) -> String {
|
|||
msg.push_str(
|
||||
traces
|
||||
.iter()
|
||||
.map(|s| format!("\n{} {}", " Trace".bold().yellow(), s.yellow()))
|
||||
.map(|s| {
|
||||
format!(
|
||||
"\n{} {}",
|
||||
" Trace"
|
||||
.if_supports_color(Stderr, |s| s.yellow())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
s.if_supports_color(Stderr, |s| s.yellow())
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
.as_str(),
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use aiken_project::{pretty, script::EvalInfo, telemetry, Project};
|
||||
use miette::IntoDiagnostic;
|
||||
use owo_colors::OwoColorize;
|
||||
use owo_colors::{
|
||||
OwoColorize,
|
||||
Stream::{self, Stderr},
|
||||
};
|
||||
use std::{collections::BTreeMap, env, path::PathBuf, process};
|
||||
use uplc::machine::cost_model::ExBudget;
|
||||
|
||||
|
@ -41,7 +44,12 @@ where
|
|||
err.report()
|
||||
}
|
||||
|
||||
println!("\n{}", "Summary".purple().bold());
|
||||
eprintln!(
|
||||
"\n{}",
|
||||
"Summary"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
|
||||
let warning_text = format!("{warning_count} warning{plural}");
|
||||
|
||||
|
@ -49,17 +57,29 @@ where
|
|||
|
||||
let error_text = format!("{} error{}", errs.len(), plural);
|
||||
|
||||
let full_summary = format!(" {}, {}", error_text.red(), warning_text.yellow());
|
||||
let full_summary = format!(
|
||||
" {}, {}",
|
||||
error_text.if_supports_color(Stderr, |s| s.red()),
|
||||
warning_text.if_supports_color(Stderr, |s| s.yellow())
|
||||
);
|
||||
|
||||
println!("{full_summary}");
|
||||
eprintln!("{full_summary}");
|
||||
|
||||
process::exit(1);
|
||||
} else {
|
||||
println!("\n{}", "Summary".purple().bold());
|
||||
eprintln!(
|
||||
"\n{}",
|
||||
"Summary"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
|
||||
let warning_text = format!("{warning_count} warning{plural}");
|
||||
|
||||
println!(" 0 errors, {}", warning_text.yellow(),);
|
||||
eprintln!(
|
||||
" 0 errors, {}",
|
||||
warning_text.if_supports_color(Stderr, |s| s.yellow()),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -75,12 +95,15 @@ impl telemetry::EventListener for Terminal {
|
|||
version,
|
||||
root,
|
||||
} => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {} {} ({})",
|
||||
" Compiling".bold().purple(),
|
||||
name.bold(),
|
||||
" Compiling"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
name.if_supports_color(Stderr, |s| s.bold()),
|
||||
version,
|
||||
root.display().bright_blue()
|
||||
root.display()
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
);
|
||||
}
|
||||
telemetry::Event::BuildingDocumentation {
|
||||
|
@ -88,65 +111,103 @@ impl telemetry::EventListener for Terminal {
|
|||
version,
|
||||
root,
|
||||
} => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {} {} ({})",
|
||||
" Generating documentation".bold().purple(),
|
||||
name.bold(),
|
||||
" Generating documentation"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
name.if_supports_color(Stderr, |s| s.bold()),
|
||||
version,
|
||||
root.to_str().unwrap_or("").bright_blue()
|
||||
root.to_str()
|
||||
.unwrap_or("")
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
);
|
||||
}
|
||||
telemetry::Event::WaitingForBuildDirLock => {
|
||||
println!("{}", "Waiting for build directory lock ...".bold().purple());
|
||||
eprintln!(
|
||||
"{}",
|
||||
"Waiting for build directory lock ..."
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
);
|
||||
}
|
||||
telemetry::Event::DumpingUPLC { path } => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {} ({})",
|
||||
" Exporting".bold().purple(),
|
||||
"UPLC".bold(),
|
||||
path.display().bright_blue()
|
||||
" Exporting"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
"UPLC".if_supports_color(Stderr, |s| s.bold()),
|
||||
path.display()
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
);
|
||||
}
|
||||
telemetry::Event::GeneratingBlueprint { path } => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {} ({})",
|
||||
" Generating".bold().purple(),
|
||||
"project's blueprint".bold(),
|
||||
path.display().bright_blue()
|
||||
" Generating"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
"project's blueprint".if_supports_color(Stderr, |s| s.bold()),
|
||||
path.display()
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
);
|
||||
}
|
||||
telemetry::Event::GeneratingDocFiles { output_path } => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} in {}",
|
||||
" Generating documentation files".bold().purple(),
|
||||
output_path.to_str().unwrap_or("").bright_blue()
|
||||
" Generating documentation files"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
output_path
|
||||
.to_str()
|
||||
.unwrap_or("")
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
);
|
||||
}
|
||||
telemetry::Event::GeneratingUPLCFor { name, path } => {
|
||||
println!(
|
||||
eprintln!(
|
||||
"{} {}.{{{}}}",
|
||||
" Generating UPLC for".bold().purple(),
|
||||
path.to_str().unwrap_or("").blue(),
|
||||
name.bright_blue(),
|
||||
" Generating UPLC for"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
path.to_str()
|
||||
.unwrap_or("")
|
||||
.if_supports_color(Stderr, |s| s.blue()),
|
||||
name.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||
);
|
||||
}
|
||||
telemetry::Event::EvaluatingFunction { results } => {
|
||||
println!("{}\n", " Evaluating function ...".bold().purple());
|
||||
eprintln!(
|
||||
"{}\n",
|
||||
" Evaluating function ..."
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
);
|
||||
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
||||
|
||||
for eval_info in &results {
|
||||
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu))
|
||||
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu, Stderr))
|
||||
}
|
||||
}
|
||||
telemetry::Event::RunningTests => {
|
||||
println!("{} {}\n", " Testing".bold().purple(), "...".bold());
|
||||
eprintln!(
|
||||
"{} {}\n",
|
||||
" Testing"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
"...".if_supports_color(Stderr, |s| s.bold())
|
||||
);
|
||||
}
|
||||
telemetry::Event::FinishedTests { tests } => {
|
||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||
|
||||
for (module, infos) in &group_by_module(&tests) {
|
||||
let title = module.bold().blue().to_string();
|
||||
let title = module
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.blue())
|
||||
.to_string();
|
||||
|
||||
let tests = infos
|
||||
.iter()
|
||||
|
@ -156,11 +217,11 @@ impl telemetry::EventListener for Terminal {
|
|||
|
||||
let summary = fmt_test_summary(infos, true);
|
||||
|
||||
println!(
|
||||
eprintln!(
|
||||
"{}\n",
|
||||
pretty::indent(
|
||||
&pretty::open_box(&title, &tests, &summary, |border| border
|
||||
.bright_black()
|
||||
.if_supports_color(Stderr, |s| s.bright_black())
|
||||
.to_string()),
|
||||
4
|
||||
)
|
||||
|
@ -168,7 +229,13 @@ impl telemetry::EventListener for Terminal {
|
|||
}
|
||||
}
|
||||
telemetry::Event::DownloadingPackage { name } => {
|
||||
println!("{} {}", " Downloading".bold().purple(), name.bold())
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
" Downloading"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
name.if_supports_color(Stderr, |s| s.bold())
|
||||
)
|
||||
}
|
||||
telemetry::Event::PackagesDownloaded { start, count } => {
|
||||
let elapsed = format!("{:.2}s", start.elapsed().as_millis() as f32 / 1000.);
|
||||
|
@ -178,10 +245,21 @@ impl telemetry::EventListener for Terminal {
|
|||
_ => format!("{count} packages in {elapsed}"),
|
||||
};
|
||||
|
||||
println!("{} {}", " Downloaded".bold().purple(), msg.bold())
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
" Downloaded"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
msg.if_supports_color(Stderr, |s| s.bold())
|
||||
)
|
||||
}
|
||||
telemetry::Event::ResolvingVersions => {
|
||||
println!("{}", " Resolving versions".bold().purple(),)
|
||||
eprintln!(
|
||||
"{}",
|
||||
" Resolving versions"
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.purple()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,13 +281,27 @@ fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool)
|
|||
let test = format!(
|
||||
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
|
||||
status = if *success {
|
||||
pretty::style_if(styled, "PASS".to_string(), |s| s.bold().green().to_string())
|
||||
pretty::style_if(styled, "PASS".to_string(), |s| {
|
||||
s.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.green())
|
||||
.to_string()
|
||||
})
|
||||
} else {
|
||||
pretty::style_if(styled, "FAIL".to_string(), |s| s.bold().red().to_string())
|
||||
pretty::style_if(styled, "FAIL".to_string(), |s| {
|
||||
s.if_supports_color(Stderr, |s| s.bold())
|
||||
.if_supports_color(Stderr, |s| s.red())
|
||||
.to_string()
|
||||
})
|
||||
},
|
||||
mem_unit = pretty::style_if(styled, mem_pad, |s| s.bright_white().to_string()),
|
||||
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s.bright_white().to_string()),
|
||||
module = pretty::style_if(styled, script.name.clone(), |s| s.bright_blue().to_string()),
|
||||
mem_unit = pretty::style_if(styled, mem_pad, |s| s
|
||||
.if_supports_color(Stderr, |s| s.bright_white())
|
||||
.to_string()),
|
||||
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s
|
||||
.if_supports_color(Stderr, |s| s.bright_white())
|
||||
.to_string()),
|
||||
module = pretty::style_if(styled, script.name.clone(), |s| s
|
||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||
.to_string()),
|
||||
);
|
||||
|
||||
let logs = if logs.is_empty() {
|
||||
|
@ -219,8 +311,8 @@ fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool)
|
|||
.map(|line| {
|
||||
format!(
|
||||
"{arrow} {styled_line}",
|
||||
arrow = "↳".bright_yellow(),
|
||||
styled_line = line.bright_black()
|
||||
arrow = "↳".if_supports_color(Stderr, |s| s.bright_yellow()),
|
||||
styled_line = line.if_supports_color(Stderr, |s| s.bright_black())
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
|
@ -247,20 +339,20 @@ fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
|
|||
format!(
|
||||
"{} | {} | {}",
|
||||
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
||||
.bold()
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.to_string()),
|
||||
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
|
||||
.bright_green()
|
||||
.bold()
|
||||
.if_supports_color(Stderr, |s| s.bright_green())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.to_string()),
|
||||
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
|
||||
.bright_red()
|
||||
.bold()
|
||||
.if_supports_color(Stderr, |s| s.bright_red())
|
||||
.if_supports_color(Stderr, |s| s.bold())
|
||||
.to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
|
||||
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, stream: Stream) -> String {
|
||||
let EvalInfo {
|
||||
output,
|
||||
script,
|
||||
|
@ -272,8 +364,8 @@ fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
|
|||
|
||||
format!(
|
||||
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
||||
script.module.blue(),
|
||||
script.name.bright_blue(),
|
||||
script.module.if_supports_color(stream, |s| s.blue()),
|
||||
script.name.if_supports_color(stream, |s| s.bright_blue()),
|
||||
pretty::pad_left(mem.to_string(), max_mem, " "),
|
||||
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
||||
output
|
||||
|
|
Loading…
Reference in New Issue