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"
|
version = "3.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
dependencies = [
|
||||||
|
"supports-color",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pallas"
|
name = "pallas"
|
||||||
|
|
|
@ -18,7 +18,7 @@ indoc = "1.0.7"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
miette = "5.2.0"
|
miette = "5.2.0"
|
||||||
ordinal = "0.3.2"
|
ordinal = "0.3.2"
|
||||||
owo-colors = "3.5.0"
|
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||||
strum = "0.24.1"
|
strum = "0.24.1"
|
||||||
thiserror = "1.0.37"
|
thiserror = "1.0.37"
|
||||||
uplc = { path = '../uplc', version = "0.0.29" }
|
uplc = { path = '../uplc', version = "0.0.29" }
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
tipo::{PatternConstructor, Type, TypeInfo},
|
tipo::{PatternConstructor, Type, TypeInfo},
|
||||||
};
|
};
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
|
|
||||||
pub const ASSERT_VARIABLE: &str = "_try";
|
pub const ASSERT_VARIABLE: &str = "_try";
|
||||||
pub const CAPTURE_VARIABLE: &str = "_capture";
|
pub const CAPTURE_VARIABLE: &str = "_capture";
|
||||||
|
@ -1190,8 +1190,8 @@ impl chumsky::Span for Span {
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(
|
#[error(
|
||||||
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
||||||
name.purple(),
|
name.if_supports_color(Stdout, |s| s.purple()),
|
||||||
keyword.purple()
|
keyword.if_supports_color(Stdout, |s| s.purple())
|
||||||
)]
|
)]
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
||||||
#[diagnostic(code("illegal::module_name"))]
|
#[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"#))]
|
as, expect, check, const, else, fn, if, is, let, opaque, pub, test, todo, trace, type, use, when"#))]
|
||||||
KeywordInModuleName { name: String, keyword: String },
|
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(code("illegal::module_name"))]
|
||||||
#[diagnostic(help(r#"Some module names are reserved for internal use. This the case of:
|
#[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 crate::{ast::Span, parser::token::Token};
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(Debug, Diagnostic, thiserror::Error)]
|
#[derive(Debug, Diagnostic, thiserror::Error)]
|
||||||
|
@ -123,8 +123,12 @@ pub enum ErrorKind {
|
||||||
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
│ {} my_policy_id {}
|
│ {} 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,
|
MalformedBase16StringLiteral,
|
||||||
|
|
||||||
#[error("I failed to understand a when clause guard.")]
|
#[error("I failed to understand a when clause guard.")]
|
||||||
|
@ -143,10 +147,10 @@ pub enum ErrorKind {
|
||||||
{bad} (x, _) if x % 3 == 0 -> ...
|
{bad} (x, _) if x % 3 == 0 -> ...
|
||||||
{bad} (x, y) if x + y > 42 -> ...
|
{bad} (x, y) if x + y > 42 -> ...
|
||||||
"#
|
"#
|
||||||
, operator_or = "||".yellow()
|
, operator_or = "||".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, operator_and = "&&".yellow()
|
, operator_and = "&&".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, good = "✔️".green()
|
, good = "✔️".if_supports_color(Stdout, |s| s.green())
|
||||||
, bad = "✖️".red()
|
, bad = "✖️".if_supports_color(Stdout, |s| s.red())
|
||||||
}))]
|
}))]
|
||||||
InvalidWhenClause,
|
InvalidWhenClause,
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,10 @@ use crate::{
|
||||||
use indoc::formatdoc;
|
use indoc::formatdoc;
|
||||||
use miette::{Diagnostic, LabeledSpan};
|
use miette::{Diagnostic, LabeledSpan};
|
||||||
use ordinal::Ordinal;
|
use ordinal::Ordinal;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{
|
||||||
|
OwoColorize,
|
||||||
|
Stream::{Stderr, Stdout},
|
||||||
|
};
|
||||||
use std::{collections::HashMap, fmt::Display, sync::Arc};
|
use std::{collections::HashMap, fmt::Display, sync::Arc};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||||
|
@ -37,7 +40,7 @@ impl Diagnostic for UnknownLabels {
|
||||||
{known_labels}"#
|
{known_labels}"#
|
||||||
, known_labels = self.valid
|
, known_labels = self.valid
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| format!("─▶ {}", s.yellow()))
|
.map(|s| format!("─▶ {}", s.if_supports_color(Stdout, |s| s.yellow())))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n")
|
.join("\n")
|
||||||
}))
|
}))
|
||||||
|
@ -85,10 +88,14 @@ pub enum Error {
|
||||||
errors: Vec<Snippet>,
|
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(code("duplicate::argument"))]
|
||||||
#[diagnostic(help("Function arguments cannot have the same name. You can use '{discard}' and numbers to distinguish between similar names."
|
#[diagnostic(help(
|
||||||
, discard = "_".yellow()
|
"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 {
|
DuplicateArgument {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -100,8 +107,9 @@ pub enum Error {
|
||||||
|
|
||||||
#[error("I found two declarations for the constant '{}'.\n", name.purple())]
|
#[error("I found two declarations for the constant '{}'.\n", name.purple())]
|
||||||
#[diagnostic(code("duplicate::constant"))]
|
#[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."
|
#[diagnostic(help(
|
||||||
, discard = "_".yellow()
|
"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 {
|
DuplicateConstName {
|
||||||
#[label("declared again here")]
|
#[label("declared again here")]
|
||||||
|
@ -111,7 +119,10 @@ pub enum Error {
|
||||||
name: String,
|
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(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.
|
#[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.
|
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})
|
│ {variant_Point}({type_Int}, {type_Int}, {type_Int})
|
||||||
│ }}
|
│ }}
|
||||||
"#
|
"#
|
||||||
, discard = "_".yellow()
|
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_pub = "pub".bright_blue()
|
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_type = "type".yellow()
|
, keyword_type = "type".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, type_Int = "Int".green()
|
, type_Int = "Int".if_supports_color(Stdout, |s| s.green())
|
||||||
, type_Point = "Point".green()
|
, type_Point = "Point".if_supports_color(Stdout, |s| s.green())
|
||||||
, variant_Point = "Point".green()
|
, variant_Point = "Point".if_supports_color(Stdout, |s| s.green())
|
||||||
))]
|
))]
|
||||||
DuplicateField {
|
DuplicateField {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -138,7 +149,10 @@ For example:
|
||||||
label: String,
|
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(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.
|
#[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:
|
For example:
|
||||||
|
@ -146,9 +160,13 @@ For example:
|
||||||
╰─▶ {keyword_use} {import} {keyword_as} {named}
|
╰─▶ {keyword_use} {import} {keyword_as} {named}
|
||||||
|
|
||||||
Otherwise, just remove the redundant import."#
|
Otherwise, just remove the redundant import."#
|
||||||
, keyword_use = "use".bright_blue()
|
, keyword_use = "use".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_as = "as".bright_blue()
|
, keyword_as = "as".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, import = module.iter().map(|x| x.purple().bold().to_string()).collect::<Vec<_>>().join("/".bold().to_string().as_ref())
|
, 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("_")
|
, named = module.join("_")
|
||||||
))]
|
))]
|
||||||
DuplicateImport {
|
DuplicateImport {
|
||||||
|
@ -160,13 +178,17 @@ Otherwise, just remove the redundant import."#
|
||||||
previous_location: Span,
|
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(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.
|
You can use '{discard}' and numbers to distinguish between similar names.
|
||||||
"#
|
"#,
|
||||||
, discard = "_".yellow()
|
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||||
))]
|
))]
|
||||||
DuplicateName {
|
DuplicateName {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -176,10 +198,14 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
||||||
name: String,
|
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(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."
|
#[diagnostic(help(
|
||||||
, cannot = "cannot".red()
|
"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 {
|
DuplicateTypeName {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -189,7 +215,10 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
||||||
name: String,
|
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(
|
#[diagnostic(url(
|
||||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
"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,
|
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(
|
#[diagnostic(url(
|
||||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
"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")]
|
#[error("I found a discarded expression not bound to a variable.\n")]
|
||||||
#[diagnostic(code("implicit_discard"))]
|
#[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}'."
|
#[diagnostic(help(
|
||||||
, keyword_let = "let".yellow()
|
"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}'.",
|
||||||
, discard = "_".yellow()
|
keyword_let = "let".if_supports_color(Stdout, |s| s.yellow()),
|
||||||
|
discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||||
))]
|
))]
|
||||||
ImplicitlyDiscardedExpression {
|
ImplicitlyDiscardedExpression {
|
||||||
#[label]
|
#[label]
|
||||||
location: Span,
|
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(url("https://aiken-lang.org/language-tour/custom-types"))]
|
||||||
#[diagnostic(code("arity::constructor"))]
|
#[diagnostic(code("arity::constructor"))]
|
||||||
IncorrectFieldsArity {
|
IncorrectFieldsArity {
|
||||||
|
@ -241,7 +278,11 @@ You can use '{discard}' and numbers to distinguish between similar names.
|
||||||
labels: Vec<String>,
|
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(url("https://aiken-lang.org/language-tour/functions#named-functions"))]
|
||||||
#[diagnostic(code("arity::invoke"))]
|
#[diagnostic(code("arity::invoke"))]
|
||||||
#[diagnostic(help(r#"Functions (and constructors) must always be called with all their arguments (comma-separated, between brackets).
|
#[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, _)
|
│ {keyword_let} increment = add(1, _)
|
||||||
"#
|
"#
|
||||||
, discard = "_".yellow()
|
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, expected = expected.purple()
|
, expected = expected.if_supports_color(Stdout, |s| s.purple())
|
||||||
, keyword_fn = "fn".yellow()
|
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_let = "let".yellow()
|
, keyword_let = "let".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, type_Int = "Int".green()
|
, type_Int = "Int".if_supports_color(Stdout, |s| s.green())
|
||||||
))]
|
))]
|
||||||
IncorrectFunctionCallArity {
|
IncorrectFunctionCallArity {
|
||||||
#[label]
|
#[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
|
// 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
|
// encounter that error. We could simplify a bit the type-checker and get rid of that error
|
||||||
// eventually.
|
// 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"))]
|
#[diagnostic(code("arity::clause"))]
|
||||||
IncorrectNumClausePatterns {
|
IncorrectNumClausePatterns {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -285,12 +330,17 @@ From there, you can define 'increment', a function that takes a single argument
|
||||||
given: usize,
|
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(url("https://aiken-lang.org/language-tour/control-flow#matching"))]
|
||||||
#[diagnostic(code("arity::pattern"))]
|
#[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}'."
|
#[diagnostic(help(
|
||||||
, discard = "_".yellow()
|
"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}'.",
|
||||||
, spread = "..".yellow()
|
discard = "_".if_supports_color(Stdout, |s| s.yellow()),
|
||||||
|
spread = "..".if_supports_color(Stdout, |s| s.yellow()),
|
||||||
))]
|
))]
|
||||||
IncorrectPatternArity {
|
IncorrectPatternArity {
|
||||||
#[label("{}", suggest_pattern(*expected, name, given, module, *is_record).unwrap_or_default())]
|
#[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,
|
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(url("https://aiken-lang.org/language-tour/control-flow#destructuring"))]
|
||||||
#[diagnostic(code("arity::tuple"))]
|
#[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}'."
|
#[diagnostic(help(
|
||||||
, discard = "_".yellow()
|
"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 {
|
IncorrectTupleArity {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -315,7 +370,11 @@ From there, you can define 'increment', a function that takes a single argument
|
||||||
given: usize,
|
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(url("https://aiken-lang.org/language-tour/custom-types#generics"))]
|
||||||
#[diagnostic(code("arity::generic"))]
|
#[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}'.
|
#[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:
|
Perhaps, try the following:
|
||||||
|
|
||||||
╰─▶ {suggestion}"#
|
╰─▶ {suggestion}"#
|
||||||
, chevron_left = "<".yellow()
|
, chevron_left = "<".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, chevron_right = ">".yellow()
|
, chevron_right = ">".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, suggestion = suggest_generic(name, *expected)
|
, suggestion = suggest_generic(name, *expected)
|
||||||
))]
|
))]
|
||||||
IncorrectTypeArity {
|
IncorrectTypeArity {
|
||||||
|
@ -337,8 +396,8 @@ Perhaps, try the following:
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
"I realized the module '{}' contains the keyword '{}', which is forbidden.\n",
|
||||||
name.purple(),
|
name.if_supports_color(Stdout, |s| s.purple()),
|
||||||
keyword.purple()
|
keyword.if_supports_color(Stdout, |s| s.purple()),
|
||||||
)]
|
)]
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/modules"))]
|
||||||
#[diagnostic(code("illegal::module_name"))]
|
#[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,
|
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(
|
#[diagnostic(url(
|
||||||
"https://aiken-lang.org/language-tour/control-flow#alternative-clause-patterns"
|
"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,
|
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(url("https://aiken-lang.org/language-tour/control-flow#checking-equality-and-ordering-in-patterns"))]
|
||||||
#[diagnostic(code("illegal::clause_guard"))]
|
#[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."))]
|
#[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(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||||
#[diagnostic(code("illegal::tuple_index"))]
|
#[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}"#,
|
||||||
, type_info = tipo.to_pretty(4).red()
|
type_info = tipo.to_pretty(0).if_supports_color(Stdout, |s| s.red())
|
||||||
))]
|
))]
|
||||||
NotATuple {
|
NotATuple {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -405,8 +471,8 @@ If you really meant to return that last expression, try to replace it with the f
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
"I realized that a given '{keyword_when}/{keyword_is}' expression is non-exhaustive.",
|
"I realized that a given '{keyword_when}/{keyword_is}' expression is non-exhaustive.",
|
||||||
keyword_is = "is".purple(),
|
keyword_is = "is".if_supports_color(Stdout, |s| s.purple()),
|
||||||
keyword_when = "when".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:
|
In this particular instance, the following cases are unmatched:
|
||||||
|
|
||||||
{missing}"#
|
{missing}"#
|
||||||
, discard = "_".yellow()
|
, discard = "_".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_is = "is".purple()
|
, keyword_is = "is".if_supports_color(Stdout, |s| s.purple())
|
||||||
, keyword_when = "when".purple()
|
, keyword_when = "when".if_supports_color(Stdout, |s| s.purple())
|
||||||
, missing = unmatched
|
, missing = unmatched
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| format!("─▶ {s}"))
|
.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")]
|
#[error("I tripped over a call attempt on something that isn't a function.\n")]
|
||||||
#[diagnostic(code("illegal::invoke"))]
|
#[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}"#,
|
||||||
, inference = tipo.to_pretty(4)
|
inference = tipo.to_pretty(0)
|
||||||
))]
|
))]
|
||||||
NotFn {
|
NotFn {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -468,8 +535,8 @@ The culprit is:
|
||||||
{type_info}
|
{type_info}
|
||||||
|
|
||||||
Maybe you meant to turn it public using the '{keyword_pub}' keyword?"#
|
Maybe you meant to turn it public using the '{keyword_pub}' keyword?"#
|
||||||
, type_info = leaked.to_pretty(4).red()
|
, type_info = leaked.to_pretty(4).if_supports_color(Stdout, |s| s.red())
|
||||||
, keyword_pub = "pub".bright_blue()
|
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
))]
|
))]
|
||||||
PrivateTypeLeak {
|
PrivateTypeLeak {
|
||||||
#[label]
|
#[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_let} foo = {keyword_fn}(x: {type_ScriptContext}) {{ x.transaction }}
|
||||||
"#
|
"#
|
||||||
, keyword_fn = "fn".yellow()
|
, keyword_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_let = "let".yellow()
|
, keyword_let = "let".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, type_ScriptContext = "ScriptContext".green()
|
, type_ScriptContext = "ScriptContext".if_supports_color(Stdout, |s| s.green())
|
||||||
))]
|
))]
|
||||||
RecordAccessUnknownType {
|
RecordAccessUnknownType {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -523,8 +590,8 @@ You can help me by providing a type-annotation for 'x', as such:
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I discovered an attempt to access the {} element of a {}-tuple.\n",
|
"I discovered an attempt to access the {} element of a {}-tuple.\n",
|
||||||
Ordinal(*index + 1).to_string().purple(),
|
Ordinal(*index + 1).to_string().if_supports_color(Stdout, |s| s.purple()),
|
||||||
size.purple()
|
size.if_supports_color(Stdout, |s| s.purple())
|
||||||
)]
|
)]
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#tuples"))]
|
||||||
#[diagnostic(code("invalid::tuple_index"))]
|
#[diagnostic(code("invalid::tuple_index"))]
|
||||||
|
@ -535,7 +602,10 @@ You can help me by providing a type-annotation for 'x', as such:
|
||||||
size: usize,
|
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(url("https://aiken-lang.org/language-tour/functions#labeled-arguments"))]
|
||||||
#[diagnostic(code("unexpected::module_name"))]
|
#[diagnostic(code("unexpected::module_name"))]
|
||||||
UnexpectedLabeledArg {
|
UnexpectedLabeledArg {
|
||||||
|
@ -544,7 +614,10 @@ You can help me by providing a type-annotation for 'x', as such:
|
||||||
label: String,
|
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(url("https://aiken-lang.org/language-tour/custom-types#named-accessors"))]
|
||||||
#[diagnostic(code("unexpected::labeled_argument"))]
|
#[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.
|
#[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}
|
╰─▶ {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)
|
, suggestion = suggest_constructor_pattern(name, args, module, *with_spread)
|
||||||
))]
|
))]
|
||||||
UnexpectedLabeledArgInPattern {
|
UnexpectedLabeledArgInPattern {
|
||||||
|
@ -579,7 +654,10 @@ Perhaps, try the following:
|
||||||
#[diagnostic(code("unknown::labels"))]
|
#[diagnostic(code("unknown::labels"))]
|
||||||
UnknownLabels(#[related] Vec<UnknownLabels>),
|
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(code("unknown::module"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -594,8 +672,8 @@ Perhaps, try the following:
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I found an unknown import '{}' from module '{}'.\n",
|
"I found an unknown import '{}' from module '{}'.\n",
|
||||||
name.purple(),
|
name.if_supports_color(Stdout, |s| s.purple()),
|
||||||
module_name.purple()
|
module_name.if_supports_color(Stdout, |s| s.purple())
|
||||||
)]
|
)]
|
||||||
#[diagnostic(code("unknown::module_field"))]
|
#[diagnostic(code("unknown::module_field"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
|
@ -615,7 +693,11 @@ Perhaps, try the following:
|
||||||
type_constructors: Vec<String>,
|
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(code("unknown::module_type"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -633,7 +715,10 @@ Perhaps, try the following:
|
||||||
type_constructors: Vec<String>,
|
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(code("unknown::module_value"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -652,14 +737,14 @@ Perhaps, try the following:
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I looked for the field '{}' in a record of type '{}' couldn't find it.\n",
|
"I looked for the field '{}' in a record of type '{}' but couldn't find it.\n",
|
||||||
label.purple(),
|
label.if_supports_color(Stdout, |s| s.purple()),
|
||||||
typ.to_pretty(4).purple()
|
typ.to_pretty(0).if_supports_color(Stdout, |s| s.purple()),
|
||||||
)]
|
)]
|
||||||
#[diagnostic(code("unknown::record_field"))]
|
#[diagnostic(code("unknown::record_field"))]
|
||||||
#[diagnostic(help(
|
#[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 {
|
UnknownRecordField {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -683,7 +768,10 @@ Perhaps, try the following:
|
||||||
types: Vec<String>,
|
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(code("unknown::type_constructor"))]
|
||||||
#[diagnostic(help(
|
#[diagnostic(help(
|
||||||
"{}",
|
"{}",
|
||||||
|
@ -737,24 +825,37 @@ The best thing to do from here is to remove it."#))]
|
||||||
location: Span,
|
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(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 {
|
ValidatorImported {
|
||||||
#[label]
|
#[label]
|
||||||
location: Span,
|
location: Span,
|
||||||
name: String,
|
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(code("illegal::validator_return_type"))]
|
||||||
#[diagnostic(help(r#"While analyzing the return type of your validator, I found it to be:
|
#[diagnostic(help(r#"While analyzing the return type of your validator, I found it to be:
|
||||||
|
|
||||||
╰─▶ {signature}
|
╰─▶ {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"#
|
...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()
|
, type_Bool = "Bool"
|
||||||
, signature = return_type.to_pretty(0).red()
|
.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 {
|
ValidatorMustReturnBool {
|
||||||
#[label("invalid return type")]
|
#[label("invalid return type")]
|
||||||
|
@ -775,7 +876,10 @@ The best thing to do from here is to remove it."#))]
|
||||||
arguments.push('s');
|
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 {
|
} else {
|
||||||
let extra = count - 3;
|
let extra = count - 3;
|
||||||
|
|
||||||
|
@ -785,7 +889,10 @@ The best thing to do from here is to remove it."#))]
|
||||||
arguments.push('s');
|
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 {
|
IncorrectValidatorArity {
|
||||||
|
@ -881,7 +988,10 @@ fn suggest_neighbor<'a>(
|
||||||
.min_by(|(_, a), (_, b)| a.cmp(b))
|
.min_by(|(_, a), (_, b)| a.cmp(b))
|
||||||
.and_then(|(suggestion, distance)| {
|
.and_then(|(suggestion, distance)| {
|
||||||
if distance <= threshold {
|
if distance <= threshold {
|
||||||
Some(format!("Did you mean '{}'?", suggestion.yellow()))
|
Some(format!(
|
||||||
|
"Did you mean '{}'?",
|
||||||
|
suggestion.if_supports_color(Stdout, |s| s.yellow())
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -962,10 +1072,10 @@ fn suggest_unify(
|
||||||
{given}
|
{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."#,
|
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_when = "when".if_supports_color(Stdout, |s| s.yellow()),
|
||||||
keyword_is = "is".yellow(),
|
keyword_is = "is".if_supports_color(Stdout, |s| s.yellow()),
|
||||||
expected = expected.green(),
|
expected = expected.if_supports_color(Stdout, |s| s.green()),
|
||||||
given = given.red()
|
given = given.if_supports_color(Stdout, |s| s.red())
|
||||||
},
|
},
|
||||||
Some(UnifyErrorSituation::ReturnAnnotationMismatch) => formatdoc! {
|
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.
|
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."#,
|
Either, fix the annotation or adjust the function body to return the expected type."#,
|
||||||
expected.green(),
|
expected.if_supports_color(Stdout, |s| s.green()),
|
||||||
given.red()
|
given.if_supports_color(Stdout, |s| s.red())
|
||||||
},
|
},
|
||||||
Some(UnifyErrorSituation::PipeTypeMismatch) => formatdoc! {
|
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.
|
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."#,
|
Either, fix the input or change the target so that both match."#,
|
||||||
expected.green(),
|
expected.if_supports_color(Stdout, |s| s.green()),
|
||||||
given.red()
|
given.if_supports_color(Stdout, |s| s.red())
|
||||||
},
|
},
|
||||||
Some(UnifyErrorSituation::Operator(op)) => formatdoc! {
|
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.
|
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(),
|
op.to_doc().to_pretty_string(70).if_supports_color(Stdout, |s| s.yellow()),
|
||||||
expected.green(),
|
expected.if_supports_color(Stdout, |s| s.green()),
|
||||||
given.red()
|
given.if_supports_color(Stdout, |s| s.red())
|
||||||
},
|
},
|
||||||
None => formatdoc! {
|
None => formatdoc! {
|
||||||
r#"I am inferring the following type:
|
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."#,
|
Either, add type-annotation to improve my inference, or adjust the expression to have the expected type."#,
|
||||||
expected.green(),
|
expected.if_supports_color(Stdout, |s| s.green()),
|
||||||
given.red()
|
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.
|
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_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_pub = "pub".bright_blue()
|
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_type = "type".yellow()
|
, keyword_type = "type".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, literal_foo = "\"foo\"".bright_purple()
|
, literal_foo = "\"foo\"".if_supports_color(Stdout, |s| s.bright_purple())
|
||||||
, type_Bar = "Bar".green()
|
, type_Bar = "Bar"
|
||||||
, variant_Bar = "Bar".green()
|
.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_fn = "fn".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_is = "is".yellow()
|
, keyword_is = "is".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, keyword_pub = "pub".bright_blue()
|
, keyword_pub = "pub".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_type = "type".yellow()
|
, keyword_type = "type".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_use = "use".bright_blue()
|
, keyword_use = "use".if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, keyword_when = "when".yellow()
|
, keyword_when = "when".if_supports_color(Stdout, |s| s.yellow())
|
||||||
, type_Pet = "Pet".green()
|
, type_Pet = "Pet"
|
||||||
, variant_Cat = "Cat".green()
|
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
, variant_Dog = "Dog".green()
|
.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.")]
|
#[error("I found a when expression with a single clause.")]
|
||||||
#[diagnostic(
|
#[diagnostic(
|
||||||
code("single_when_clause"),
|
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 {
|
SingleWhenClause {
|
||||||
#[label("use let")]
|
#[label("use let")]
|
||||||
|
@ -1137,10 +1261,19 @@ pub enum Warning {
|
||||||
sample: UntypedExpr,
|
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(
|
#[diagnostic(
|
||||||
code("single_constructor_expect"),
|
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 {
|
SingleConstructorExpect {
|
||||||
#[label("use let")]
|
#[label("use let")]
|
||||||
|
@ -1161,7 +1294,10 @@ pub enum Warning {
|
||||||
tipo: Arc<Type>,
|
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(
|
#[diagnostic(help(
|
||||||
"No big deal, but you might want to remove it to get rid of that warning."
|
"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,
|
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(
|
#[diagnostic(help(
|
||||||
"No big deal, but you might want to remove it to get rid of that warning."
|
"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,
|
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(
|
#[diagnostic(help(
|
||||||
"No big deal, but you might want to remove it to get rid of that warning."
|
"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,
|
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(
|
#[diagnostic(help(
|
||||||
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
||||||
Otherwise, you might want to get rid of it altogether."
|
Otherwise, you might want to get rid of it altogether.",
|
||||||
, keyword_pub = "pub".bright_blue()
|
keyword_pub = "pub".if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
))]
|
))]
|
||||||
#[diagnostic(code("unused::function"))]
|
#[diagnostic(code("unused::function"))]
|
||||||
UnusedPrivateFunction {
|
UnusedPrivateFunction {
|
||||||
|
@ -1215,11 +1360,14 @@ pub enum Warning {
|
||||||
name: String,
|
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(
|
#[diagnostic(help(
|
||||||
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
"Perhaps your forgot to make it public using the '{keyword_pub}' keyword?\n\
|
||||||
Otherwise, you might want to get rid of it altogether."
|
Otherwise, you might want to get rid of it altogether.",
|
||||||
, keyword_pub = "pub".bright_blue()
|
keyword_pub = "pub".if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
))]
|
))]
|
||||||
#[diagnostic(code("unused::constant"))]
|
#[diagnostic(code("unused::constant"))]
|
||||||
UnusedPrivateModuleConstant {
|
UnusedPrivateModuleConstant {
|
||||||
|
@ -1228,7 +1376,10 @@ pub enum Warning {
|
||||||
name: String,
|
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"))]
|
#[diagnostic(code("unused::type"))]
|
||||||
UnusedType {
|
UnusedType {
|
||||||
#[label]
|
#[label]
|
||||||
|
@ -1248,10 +1399,13 @@ pub enum Warning {
|
||||||
name: String,
|
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(
|
#[diagnostic(help(
|
||||||
"No big deal, but you might want to move it to a {} module\nor remove it to get rid of that warning.",
|
"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"))]
|
#[diagnostic(code("unused::validator"))]
|
||||||
ValidatorInLibraryModule {
|
ValidatorInLibraryModule {
|
||||||
|
@ -1261,7 +1415,9 @@ pub enum Warning {
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
"I noticed a suspicious {type_ByteArray} UTF-8 literal which resembles a hash digest.",
|
"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! {
|
#[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}.
|
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}
|
╰─▶ {symbol_hash}{value}
|
||||||
"#,
|
"#,
|
||||||
type_ByteArray = "ByteArray".bold().bright_blue(),
|
type_ByteArray = "ByteArray"
|
||||||
literal_foo = "\"foo\"".purple(),
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
foo_bytes = "#[102, 111, 111]".purple(),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
value = "\"{value}\"".purple(),
|
literal_foo = "\"foo\"".if_supports_color(Stderr, |s| s.purple()),
|
||||||
symbol_hash = "#".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(code("syntax::bytearray_literal_is_hex_string"))]
|
||||||
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#bytearray"))]
|
#[diagnostic(url("https://aiken-lang.org/language-tour/primitive-types#bytearray"))]
|
||||||
|
@ -1314,9 +1472,11 @@ fn format_suggestion(sample: &UntypedExpr) -> String {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(ix, line)| {
|
.map(|(ix, line)| {
|
||||||
if ix == 0 {
|
if ix == 0 {
|
||||||
format!("╰─▶ {}", line.yellow())
|
format!("╰─▶ {}", line.if_supports_color(Stdout, |s| s.yellow()))
|
||||||
} else {
|
} else {
|
||||||
format!(" {line}").yellow().to_string()
|
format!(" {line}")
|
||||||
|
.if_supports_color(Stdout, |s| s.yellow())
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|
|
@ -20,7 +20,7 @@ ignore = "0.4.18"
|
||||||
indexmap = "1.9.1"
|
indexmap = "1.9.1"
|
||||||
itertools = "0.10.1"
|
itertools = "0.10.1"
|
||||||
miette = { version = "5.3.0", features = ["fancy"] }
|
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 = "0.16.0"
|
||||||
pallas-traverse = "0.16.0"
|
pallas-traverse = "0.16.0"
|
||||||
petgraph = "0.6.2"
|
petgraph = "0.6.2"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::schema;
|
use super::schema;
|
||||||
use aiken_lang::ast::Span;
|
use aiken_lang::ast::Span;
|
||||||
use miette::{Diagnostic, NamedSource};
|
use miette::{Diagnostic, NamedSource};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||||
|
@ -19,15 +19,25 @@ pub enum Error {
|
||||||
|
|
||||||
#[error("Invalid or missing project's blueprint file.")]
|
#[error("Invalid or missing project's blueprint file.")]
|
||||||
#[diagnostic(code("aiken::blueprint::missing"))]
|
#[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,
|
InvalidOrMissingFile,
|
||||||
|
|
||||||
#[error("I didn't find any parameters to apply in the given validator.")]
|
#[error("I didn't find any parameters to apply in the given validator.")]
|
||||||
#[diagnostic(code("aiken::blueprint::apply::no_parameters"))]
|
#[diagnostic(code("aiken::blueprint::apply::no_parameters"))]
|
||||||
NoParametersToApply,
|
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(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 },
|
ParameterizedValidator { n: usize },
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use aiken_lang::{
|
||||||
ast::{DataType, Definition, TypedDefinition},
|
ast::{DataType, Definition, TypedDefinition},
|
||||||
tipo::{pretty, Type, TypeVar},
|
tipo::{pretty, Type, TypeVar},
|
||||||
};
|
};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
use serde::{
|
use serde::{
|
||||||
self,
|
self,
|
||||||
ser::{Serialize, SerializeStruct, Serializer},
|
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.
|
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."#,
|
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!(
|
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:
|
There are few restrictions like this one. In this instance, here's the types I followed and that led me to this problem:
|
||||||
|
|
||||||
╰─▶ {breadcrumbs}"#,
|
╰─▶ {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)
|
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()
|
pretty::Printer::new()
|
||||||
.print(type_info)
|
.print(type_info)
|
||||||
.to_pretty_string(70)
|
.to_pretty_string(70)
|
||||||
.bright_blue()
|
.if_supports_color(Stdout, |s| s.bright_blue())
|
||||||
.bold()
|
.if_supports_color(Stdout, |s| s.bold())
|
||||||
.to_string()
|
.to_string()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
|
|
@ -10,7 +10,7 @@ use aiken_lang::{
|
||||||
use miette::{
|
use miette::{
|
||||||
Diagnostic, EyreContext, LabeledSpan, MietteHandlerOpts, NamedSource, RgbColors, SourceCode,
|
Diagnostic, EyreContext, LabeledSpan, MietteHandlerOpts, NamedSource, RgbColors, SourceCode,
|
||||||
};
|
};
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stdout};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
io,
|
io,
|
||||||
|
@ -121,7 +121,7 @@ pub enum Error {
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
pub fn report(&self) {
|
pub fn report(&self) {
|
||||||
eprintln!("Error: {self:?}")
|
println!("{self:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_parse_errors(errs: Vec<ParseError>, path: &Path, src: &str) -> Vec<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 } => {
|
Error::NoValidatorNotFound { known_validators } => {
|
||||||
Some(Box::new(format!(
|
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{}",
|
"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 } => {
|
Error::MoreThanOneValidatorFound { known_validators } => {
|
||||||
Some(Box::new(format!(
|
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{}",
|
"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(),
|
Error::Module(e) => e.help(),
|
||||||
|
@ -526,7 +540,7 @@ impl Warning {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn report(&self) {
|
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 serde::{de::Visitor, Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
|
@ -109,12 +109,19 @@ impl<'de> Deserialize<'de> for PackageName {
|
||||||
|
|
||||||
#[derive(Debug, Error, miette::Diagnostic)]
|
#[derive(Debug, Error, miette::Diagnostic)]
|
||||||
pub enum Error {
|
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 {
|
InvalidProjectName {
|
||||||
name: String,
|
name: String,
|
||||||
reason: InvalidProjectNameReason,
|
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 },
|
ProjectExists { name: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,9 +141,9 @@ impl fmt::Display for InvalidProjectNameReason {
|
||||||
{}/{}\n\nEach part must start with a lowercase letter \
|
{}/{}\n\nEach part must start with a lowercase letter \
|
||||||
and may only contain lowercase letters, numbers, hyphens or underscores.\
|
and may only contain lowercase letters, numbers, hyphens or underscores.\
|
||||||
\nFor example,\n\n\t{}",
|
\nFor example,\n\n\t{}",
|
||||||
"{owner}".bright_blue(),
|
"{owner}".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||||
"{project}".bright_blue(),
|
"{project}".if_supports_color(Stdout, |s| s.bright_blue()),
|
||||||
"aiken-lang/stdlib".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"
|
ignore = "0.4.18"
|
||||||
indoc = "1.0"
|
indoc = "1.0"
|
||||||
miette = { version = "5.3.0", features = ["fancy"] }
|
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-addresses = "0.16.0"
|
||||||
pallas-codec = "0.16.0"
|
pallas-codec = "0.16.0"
|
||||||
pallas-crypto = "0.16.0"
|
pallas-crypto = "0.16.0"
|
||||||
|
|
|
@ -4,7 +4,7 @@ use aiken_project::{
|
||||||
};
|
};
|
||||||
use indoc::{formatdoc, indoc};
|
use indoc::{formatdoc, indoc};
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -55,7 +55,7 @@ fn create_project(args: Args, package_name: &PackageName) -> miette::Result<()>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_success_message(package_name: &PackageName) {
|
fn print_success_message(package_name: &PackageName) {
|
||||||
println!(
|
eprintln!(
|
||||||
"\n{}",
|
"\n{}",
|
||||||
formatdoc! {
|
formatdoc! {
|
||||||
r#"Your Aiken project {name} has been {s} created.
|
r#"Your Aiken project {name} has been {s} created.
|
||||||
|
@ -64,10 +64,17 @@ fn print_success_message(package_name: &PackageName) {
|
||||||
{cd} {name}
|
{cd} {name}
|
||||||
{aiken} check
|
{aiken} check
|
||||||
"#,
|
"#,
|
||||||
s = "successfully".bold().bright_green(),
|
s = "successfully"
|
||||||
cd = "cd".bold().purple(),
|
.if_supports_color(Stderr, |s| s.bright_green())
|
||||||
name = package_name.repo.bright_blue(),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
aiken = "aiken".bold().purple(),
|
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,
|
pretty,
|
||||||
};
|
};
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
use std::{path::PathBuf, process, str::FromStr};
|
use std::{path::PathBuf, process, str::FromStr};
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
|
@ -43,27 +43,29 @@ pub fn exec(args: Args) -> miette::Result<()> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
pretty::pad_left("Package".to_string(), 13, " ")
|
pretty::pad_left("Package".to_string(), 13, " ")
|
||||||
.bold()
|
.bold()
|
||||||
.purple(),
|
.purple(),
|
||||||
dependency.name.bright_blue(),
|
dependency
|
||||||
|
.name
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||||
);
|
);
|
||||||
|
|
||||||
match config.insert(&dependency, args.overwrite) {
|
match config.insert(&dependency, args.overwrite) {
|
||||||
Some(config) => {
|
Some(config) => {
|
||||||
config.save(&root).into_diagnostic()?;
|
config.save(&root).into_diagnostic()?;
|
||||||
println!(
|
eprintln!(
|
||||||
"{} version → {}",
|
"{} version → {}",
|
||||||
pretty::pad_left(
|
pretty::pad_left(
|
||||||
if args.overwrite { "Changed" } else { "Added" }.to_string(),
|
if args.overwrite { "Changed" } else { "Added" }.to_string(),
|
||||||
13,
|
13,
|
||||||
" "
|
" "
|
||||||
)
|
)
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
.purple(),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
dependency.version.yellow()
|
dependency.version.if_supports_color(Stderr, |s| s.yellow())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
use aiken_project::{paths, pretty};
|
use aiken_project::{paths, pretty};
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
pub fn exec() -> miette::Result<()> {
|
pub fn exec() -> miette::Result<()> {
|
||||||
let dir = paths::packages_cache();
|
let dir = paths::packages_cache();
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
pretty::pad_left("Clearing".to_string(), 13, " ")
|
pretty::pad_left("Clearing".to_string(), 13, " ")
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
.purple(),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
dir.display().bold(),
|
dir.display().if_supports_color(Stderr, |s| s.bold()),
|
||||||
);
|
);
|
||||||
let packages = fs::read_dir(&dir).into_diagnostic()?;
|
let packages = fs::read_dir(&dir).into_diagnostic()?;
|
||||||
for package in packages {
|
for package in packages {
|
||||||
let path = package.into_diagnostic()?.path();
|
let path = package.into_diagnostic()?.path();
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
pretty::pad_left("Removing".to_string(), 13, " ")
|
pretty::pad_left("Removing".to_string(), 13, " ")
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
.purple(),
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
path.file_name()
|
path.file_name()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.bright_blue(),
|
.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||||
);
|
);
|
||||||
fs::remove_file(path).into_diagnostic()?;
|
fs::remove_file(path).into_diagnostic()?;
|
||||||
}
|
}
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
pretty::pad_left("Done".to_string(), 13, " ")
|
pretty::pad_left("Done".to_string(), 13, " ")
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
.purple()
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
use pallas_primitives::{
|
use pallas_primitives::{
|
||||||
babbage::{Redeemer, TransactionInput, TransactionOutput},
|
babbage::{Redeemer, TransactionInput, TransactionOutput},
|
||||||
Fragment,
|
Fragment,
|
||||||
|
@ -54,7 +54,12 @@ pub fn exec(
|
||||||
zero_slot,
|
zero_slot,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> 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 {
|
let (tx_bytes, inputs_bytes, outputs_bytes) = if cbor {
|
||||||
(
|
(
|
||||||
|
@ -78,7 +83,13 @@ pub fn exec(
|
||||||
.or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))
|
.or_else(|_| MultiEraTx::decode(Era::Alonzo, &tx_bytes))
|
||||||
.into_diagnostic()?;
|
.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 inputs = Vec::<TransactionInput>::decode_fragment(&inputs_bytes).unwrap();
|
||||||
let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap();
|
let outputs = Vec::<TransactionOutput>::decode_fragment(&outputs_bytes).unwrap();
|
||||||
|
@ -100,9 +111,11 @@ pub fn exec(
|
||||||
};
|
};
|
||||||
|
|
||||||
let with_redeemer = |redeemer: &Redeemer| {
|
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.tag,
|
||||||
redeemer.index
|
redeemer.index
|
||||||
)
|
)
|
||||||
|
@ -147,7 +160,13 @@ pub fn exec(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_tx_error(err: &tx::error::Error) -> String {
|
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 {
|
match err {
|
||||||
tx::error::Error::RedeemerError { err, .. } => {
|
tx::error::Error::RedeemerError { err, .. } => {
|
||||||
msg.push_str(&format!(
|
msg.push_str(&format!(
|
||||||
|
@ -164,7 +183,15 @@ fn display_tx_error(err: &tx::error::Error) -> String {
|
||||||
msg.push_str(
|
msg.push_str(
|
||||||
traces
|
traces
|
||||||
.iter()
|
.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<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("")
|
.join("")
|
||||||
.as_str(),
|
.as_str(),
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use aiken_project::{pretty, script::EvalInfo, telemetry, Project};
|
use aiken_project::{pretty, script::EvalInfo, telemetry, Project};
|
||||||
use miette::IntoDiagnostic;
|
use miette::IntoDiagnostic;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::{
|
||||||
|
OwoColorize,
|
||||||
|
Stream::{self, Stderr},
|
||||||
|
};
|
||||||
use std::{collections::BTreeMap, env, path::PathBuf, process};
|
use std::{collections::BTreeMap, env, path::PathBuf, process};
|
||||||
use uplc::machine::cost_model::ExBudget;
|
use uplc::machine::cost_model::ExBudget;
|
||||||
|
|
||||||
|
@ -41,7 +44,12 @@ where
|
||||||
err.report()
|
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}");
|
let warning_text = format!("{warning_count} warning{plural}");
|
||||||
|
|
||||||
|
@ -49,17 +57,29 @@ where
|
||||||
|
|
||||||
let error_text = format!("{} error{}", errs.len(), plural);
|
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);
|
process::exit(1);
|
||||||
} else {
|
} 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}");
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -75,12 +95,15 @@ impl telemetry::EventListener for Terminal {
|
||||||
version,
|
version,
|
||||||
root,
|
root,
|
||||||
} => {
|
} => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {} {} ({})",
|
"{} {} {} ({})",
|
||||||
" Compiling".bold().purple(),
|
" Compiling"
|
||||||
name.bold(),
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bold()),
|
||||||
version,
|
version,
|
||||||
root.display().bright_blue()
|
root.display()
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
telemetry::Event::BuildingDocumentation {
|
telemetry::Event::BuildingDocumentation {
|
||||||
|
@ -88,65 +111,103 @@ impl telemetry::EventListener for Terminal {
|
||||||
version,
|
version,
|
||||||
root,
|
root,
|
||||||
} => {
|
} => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {} {} ({})",
|
"{} {} {} ({})",
|
||||||
" Generating documentation".bold().purple(),
|
" Generating documentation"
|
||||||
name.bold(),
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bold()),
|
||||||
version,
|
version,
|
||||||
root.to_str().unwrap_or("").bright_blue()
|
root.to_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
telemetry::Event::WaitingForBuildDirLock => {
|
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 } => {
|
telemetry::Event::DumpingUPLC { path } => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {} ({})",
|
"{} {} ({})",
|
||||||
" Exporting".bold().purple(),
|
" Exporting"
|
||||||
"UPLC".bold(),
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
path.display().bright_blue()
|
.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 } => {
|
telemetry::Event::GeneratingBlueprint { path } => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {} ({})",
|
"{} {} ({})",
|
||||||
" Generating".bold().purple(),
|
" Generating"
|
||||||
"project's blueprint".bold(),
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
path.display().bright_blue()
|
.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 } => {
|
telemetry::Event::GeneratingDocFiles { output_path } => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} in {}",
|
"{} in {}",
|
||||||
" Generating documentation files".bold().purple(),
|
" Generating documentation files"
|
||||||
output_path.to_str().unwrap_or("").bright_blue()
|
.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 } => {
|
telemetry::Event::GeneratingUPLCFor { name, path } => {
|
||||||
println!(
|
eprintln!(
|
||||||
"{} {}.{{{}}}",
|
"{} {}.{{{}}}",
|
||||||
" Generating UPLC for".bold().purple(),
|
" Generating UPLC for"
|
||||||
path.to_str().unwrap_or("").blue(),
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
name.bright_blue(),
|
.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 } => {
|
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);
|
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
||||||
|
|
||||||
for eval_info in &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 => {
|
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 } => {
|
telemetry::Event::FinishedTests { tests } => {
|
||||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||||
|
|
||||||
for (module, infos) in &group_by_module(&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
|
let tests = infos
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -156,11 +217,11 @@ impl telemetry::EventListener for Terminal {
|
||||||
|
|
||||||
let summary = fmt_test_summary(infos, true);
|
let summary = fmt_test_summary(infos, true);
|
||||||
|
|
||||||
println!(
|
eprintln!(
|
||||||
"{}\n",
|
"{}\n",
|
||||||
pretty::indent(
|
pretty::indent(
|
||||||
&pretty::open_box(&title, &tests, &summary, |border| border
|
&pretty::open_box(&title, &tests, &summary, |border| border
|
||||||
.bright_black()
|
.if_supports_color(Stderr, |s| s.bright_black())
|
||||||
.to_string()),
|
.to_string()),
|
||||||
4
|
4
|
||||||
)
|
)
|
||||||
|
@ -168,7 +229,13 @@ impl telemetry::EventListener for Terminal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
telemetry::Event::DownloadingPackage { name } => {
|
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 } => {
|
telemetry::Event::PackagesDownloaded { start, count } => {
|
||||||
let elapsed = format!("{:.2}s", start.elapsed().as_millis() as f32 / 1000.);
|
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}"),
|
_ => 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 => {
|
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!(
|
let test = format!(
|
||||||
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
|
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
|
||||||
status = if *success {
|
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 {
|
} 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()),
|
mem_unit = pretty::style_if(styled, mem_pad, |s| s
|
||||||
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s.bright_white().to_string()),
|
.if_supports_color(Stderr, |s| s.bright_white())
|
||||||
module = pretty::style_if(styled, script.name.clone(), |s| s.bright_blue().to_string()),
|
.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() {
|
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| {
|
.map(|line| {
|
||||||
format!(
|
format!(
|
||||||
"{arrow} {styled_line}",
|
"{arrow} {styled_line}",
|
||||||
arrow = "↳".bright_yellow(),
|
arrow = "↳".if_supports_color(Stderr, |s| s.bright_yellow()),
|
||||||
styled_line = line.bright_black()
|
styled_line = line.if_supports_color(Stderr, |s| s.bright_black())
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
@ -247,20 +339,20 @@ fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} | {} | {}",
|
"{} | {} | {}",
|
||||||
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
.to_string()),
|
.to_string()),
|
||||||
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
|
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
|
||||||
.bright_green()
|
.if_supports_color(Stderr, |s| s.bright_green())
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
.to_string()),
|
.to_string()),
|
||||||
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
|
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
|
||||||
.bright_red()
|
.if_supports_color(Stderr, |s| s.bright_red())
|
||||||
.bold()
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
.to_string()),
|
.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 {
|
let EvalInfo {
|
||||||
output,
|
output,
|
||||||
script,
|
script,
|
||||||
|
@ -272,8 +364,8 @@ fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize) -> String {
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
||||||
script.module.blue(),
|
script.module.if_supports_color(stream, |s| s.blue()),
|
||||||
script.name.bright_blue(),
|
script.name.if_supports_color(stream, |s| s.bright_blue()),
|
||||||
pretty::pad_left(mem.to_string(), max_mem, " "),
|
pretty::pad_left(mem.to_string(), max_mem, " "),
|
||||||
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
||||||
output
|
output
|
||||||
|
|
Loading…
Reference in New Issue