Provide better errors when failing to match validators in blueprint apply.
Signed-off-by: KtorZ <matthias.benkort@gmail.com>
This commit is contained in:
parent
38252ef449
commit
f3ed727a01
|
@ -14,12 +14,10 @@
|
||||||
- **aiken-lang**: Change default placeholder for `trace` to `Void` instead of `todo`. @KtorZ
|
- **aiken-lang**: Change default placeholder for `trace` to `Void` instead of `todo`. @KtorZ
|
||||||
- **aiken-lang**: Disallow (parse error) dangling colon `:` in traces. See [#1113](https://github.com/aiken-lang/aiken/issues/1113). @KtorZ
|
- **aiken-lang**: Disallow (parse error) dangling colon `:` in traces. See [#1113](https://github.com/aiken-lang/aiken/issues/1113). @KtorZ
|
||||||
- **aiken-lang**: Fix `aiken blueprint apply` wrongly overriding all validators handlers names & ABI to the mint's one. See [#1099](https://github.com/aiken-lang/aiken/issues/1099). @KtorZ
|
- **aiken-lang**: Fix `aiken blueprint apply` wrongly overriding all validators handlers names & ABI to the mint's one. See [#1099](https://github.com/aiken-lang/aiken/issues/1099). @KtorZ
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- **aiken-lang**: Formatter was removing comments from function type annotation args @rvcas
|
- **aiken-lang**: Formatter was removing comments from function type annotation args @rvcas
|
||||||
- **aiken-lang**: Parser wrongly merged two adjacent sequences together, effectively fusioning scopes. @KtorZ
|
- **aiken-lang**: Parser wrongly merged two adjacent sequences together, effectively fusioning scopes. @KtorZ
|
||||||
- **aiken-lang**: Fix hint when suggesting to use named fields, wrongly suggesting args in lexicographical order instead of definition order. @KtorZ
|
- **aiken-lang**: Fix hint when suggesting to use named fields, wrongly suggesting args in lexicographical order instead of definition order. @KtorZ
|
||||||
|
- **aiken-project**: Better errors on `blueprint apply` when matching multiple or no validators. See [#1127](https://github.com/aiken-lang/aiken/issues/1127) @KtorZ
|
||||||
|
|
||||||
## v1.1.13 - 2025-02-26
|
## v1.1.13 - 2025-02-26
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use aiken_lang::gen_uplc::CodeGenerator;
|
||||||
use definitions::Definitions;
|
use definitions::Definitions;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
use schema::{Annotated, Schema};
|
use schema::{Annotated, Schema};
|
||||||
use std::fmt::Debug;
|
use std::{collections::BTreeSet, fmt::Debug};
|
||||||
use validator::Validator;
|
use validator::Validator;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
@ -99,15 +99,7 @@ impl Blueprint {
|
||||||
let mut validator = None;
|
let mut validator = None;
|
||||||
|
|
||||||
for v in self.validators.iter() {
|
for v in self.validators.iter() {
|
||||||
let mut split = v.title.split('.');
|
let (known_module_name, known_validator_name) = v.get_module_and_name();
|
||||||
|
|
||||||
let known_module_name = split
|
|
||||||
.next()
|
|
||||||
.expect("validator's name must have two dot-separated components.");
|
|
||||||
|
|
||||||
let known_validator_name = split
|
|
||||||
.next()
|
|
||||||
.expect("validator's name must have two dot-separated components.");
|
|
||||||
|
|
||||||
let is_target = match (want_module_name, want_validator_name) {
|
let is_target = match (want_module_name, want_validator_name) {
|
||||||
(None, None) => true,
|
(None, None) => true,
|
||||||
|
@ -143,8 +135,8 @@ impl Blueprint {
|
||||||
&self,
|
&self,
|
||||||
module_name: Option<&str>,
|
module_name: Option<&str>,
|
||||||
validator_name: Option<&str>,
|
validator_name: Option<&str>,
|
||||||
when_too_many: fn(Vec<String>) -> E,
|
when_too_many: fn(BTreeSet<(String, String, bool)>) -> E,
|
||||||
when_missing: fn(Vec<String>) -> E,
|
when_missing: fn(BTreeSet<(String, String, bool)>) -> E,
|
||||||
action: F,
|
action: F,
|
||||||
) -> Result<A, E>
|
) -> Result<A, E>
|
||||||
where
|
where
|
||||||
|
@ -153,10 +145,35 @@ impl Blueprint {
|
||||||
match self.lookup(module_name, validator_name) {
|
match self.lookup(module_name, validator_name) {
|
||||||
Some(LookupResult::One(_, validator)) => action(validator),
|
Some(LookupResult::One(_, validator)) => action(validator),
|
||||||
Some(LookupResult::Many) => Err(when_too_many(
|
Some(LookupResult::Many) => Err(when_too_many(
|
||||||
self.validators.iter().map(|v| v.title.clone()).collect(),
|
self.validators
|
||||||
|
.iter()
|
||||||
|
.filter_map(|v| {
|
||||||
|
let (l, r) = v.get_module_and_name();
|
||||||
|
|
||||||
|
if let Some(module_name) = module_name {
|
||||||
|
if l != module_name {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(validator_name) = validator_name {
|
||||||
|
if r != validator_name {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((l.to_string(), r.to_string(), !v.parameters.is_empty()))
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
)),
|
)),
|
||||||
None => Err(when_missing(
|
None => Err(when_missing(
|
||||||
self.validators.iter().map(|v| v.title.clone()).collect(),
|
self.validators
|
||||||
|
.iter()
|
||||||
|
.map(|v| {
|
||||||
|
let (l, r) = v.get_module_and_name();
|
||||||
|
(l.to_string(), r.to_string(), !v.parameters.is_empty())
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,20 @@ pub struct Validator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validator {
|
impl Validator {
|
||||||
|
pub fn get_module_and_name(&self) -> (&str, &str) {
|
||||||
|
let mut split = self.title.split('.');
|
||||||
|
|
||||||
|
let known_module_name = split
|
||||||
|
.next()
|
||||||
|
.expect("validator's name must have two dot-separated components.");
|
||||||
|
|
||||||
|
let known_validator_name = split
|
||||||
|
.next()
|
||||||
|
.expect("validator's name must have two dot-separated components.");
|
||||||
|
|
||||||
|
(known_module_name, known_validator_name)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_checked_module(
|
pub fn from_checked_module(
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
|
|
|
@ -15,6 +15,7 @@ use owo_colors::{
|
||||||
Stream::{Stderr, Stdout},
|
Stream::{Stderr, Stdout},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::BTreeSet,
|
||||||
fmt::{self, Debug, Display},
|
fmt::{self, Debug, Display},
|
||||||
io,
|
io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
@ -137,10 +138,14 @@ pub enum Error {
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error("I didn't find any validator matching your criteria.")]
|
#[error("I didn't find any validator matching your criteria.")]
|
||||||
NoValidatorNotFound { known_validators: Vec<String> },
|
NoValidatorNotFound {
|
||||||
|
known_validators: BTreeSet<(String, String, bool)>,
|
||||||
|
},
|
||||||
|
|
||||||
#[error("I found multiple suitable validators and I need you to tell me which one to pick.")]
|
#[error("I found multiple suitable validators and I need you to tell me which one to pick.")]
|
||||||
MoreThanOneValidatorFound { known_validators: Vec<String> },
|
MoreThanOneValidatorFound {
|
||||||
|
known_validators: BTreeSet<(String, String, bool)>,
|
||||||
|
},
|
||||||
|
|
||||||
#[error("I couldn't find any exportable function named '{name}' in module '{module}'.")]
|
#[error("I couldn't find any exportable function named '{name}' in module '{module}'.")]
|
||||||
ExportNotFound { module: String, name: String },
|
ExportNotFound { module: String, name: String },
|
||||||
|
@ -423,27 +428,13 @@ impl Diagnostic for Error {
|
||||||
None => String::new(),
|
None => String::new(),
|
||||||
}
|
}
|
||||||
))),
|
))),
|
||||||
Error::NoValidatorNotFound { known_validators } => Some(Box::new(format!(
|
Error::NoValidatorNotFound { known_validators } => Some(Box::new(hint_validators(
|
||||||
"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,
|
||||||
known_validators
|
"Here's a list of all validators I've found in your project.\nPlease double-check this list against the options that you've provided."
|
||||||
.iter()
|
|
||||||
.map(|title| format!(
|
|
||||||
"→ {title}",
|
|
||||||
title = title.if_supports_color(Stdout, |s| s.purple())
|
|
||||||
))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("\n")
|
|
||||||
))),
|
))),
|
||||||
Error::MoreThanOneValidatorFound { known_validators } => Some(Box::new(format!(
|
Error::MoreThanOneValidatorFound { known_validators } => Some(Box::new(hint_validators(
|
||||||
"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,
|
||||||
known_validators
|
"Here's a list of matching validators I've found in your project.\nPlease narrow the selection using additional options.",
|
||||||
.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(),
|
||||||
}
|
}
|
||||||
|
@ -809,3 +800,53 @@ fn default_miette_handler(context_lines: usize) -> MietteHandler {
|
||||||
.context_lines(context_lines)
|
.context_lines(context_lines)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hint_validators(known_validators: &BTreeSet<(String, String, bool)>, hint: &str) -> String {
|
||||||
|
let (pad_module, pad_validator) = known_validators.iter().fold(
|
||||||
|
(9, 12),
|
||||||
|
|(module_len, validator_len), (module, validator, _)| {
|
||||||
|
(
|
||||||
|
module_len.max(module.len()),
|
||||||
|
validator_len.max(validator.len()),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"{hint}\n\n\
|
||||||
|
{:<pad_module$} {:<pad_validator$}\n\
|
||||||
|
{:─<pad_module$}┒ ┎{:─<pad_validator$}\n\
|
||||||
|
{}\n\nFor convenience, I have highlighted in {bold_green} suitable candidates that {has_params}.",
|
||||||
|
"module(s)",
|
||||||
|
"validator(s)",
|
||||||
|
"─",
|
||||||
|
"─",
|
||||||
|
{
|
||||||
|
known_validators
|
||||||
|
.iter()
|
||||||
|
.map(|(module, validator, has_params)| {
|
||||||
|
let title = format!(
|
||||||
|
"{:>pad_module$} . {:<pad_validator$}",
|
||||||
|
module,
|
||||||
|
validator,
|
||||||
|
);
|
||||||
|
if *has_params {
|
||||||
|
title
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.green())
|
||||||
|
.to_string()
|
||||||
|
} else {
|
||||||
|
title
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n")
|
||||||
|
},
|
||||||
|
bold_green = "bold green"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.green()),
|
||||||
|
has_params = "can take parameters"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.green()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue