Suggest possible candidate on unknown imports.
## Before ``` × Type-checking ╰─▶ Unknown module field 'ValidityRaneg' in module 'aiken/transaction' ``` ## After ``` × Type-checking ╰─▶ Unknown import 'ValidityRaneg' from module 'aiken/transaction' ╭─[../stdlib/validators/tmp.ak:2:1] 2 │ use aiken/interval.{Interval, IntervalBound, IntervalBoundType} 3 │ use aiken/transaction.{ScriptContext, ValidityRaneg} · ───────────── 4 │ ╰──── help: Did you mean to import 'ValidityRange'? ```
This commit is contained in:
parent
70b1ec4324
commit
aa2a235790
|
@ -783,21 +783,13 @@ impl<'a> Environment<'a> {
|
|||
};
|
||||
} else if !value_imported {
|
||||
// Error if no type or value was found with that name
|
||||
return Err(Error::UnknownModuleField {
|
||||
location: *location,
|
||||
name: name.clone(),
|
||||
module_name: module.join("/"),
|
||||
value_constructors: module_info
|
||||
.values
|
||||
.keys()
|
||||
.map(|t| t.to_string())
|
||||
.collect(),
|
||||
type_constructors: module_info
|
||||
.types
|
||||
.keys()
|
||||
.map(|t| t.to_string())
|
||||
.collect(),
|
||||
});
|
||||
return Err(Error::unknown_module_field(
|
||||
*location,
|
||||
name.clone(),
|
||||
module.join("/"),
|
||||
module_info.values.keys().map(|t| t.to_string()).collect(),
|
||||
module_info.types.keys().map(|t| t.to_string()).collect(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,10 @@ use ordinal::Ordinal;
|
|||
|
||||
use miette::Diagnostic;
|
||||
|
||||
use crate::ast::{BinOp, Span, TodoKind};
|
||||
use crate::{
|
||||
ast::{BinOp, Span, TodoKind},
|
||||
levenshtein,
|
||||
};
|
||||
|
||||
use super::Type;
|
||||
|
||||
|
@ -175,13 +178,15 @@ pub enum Error {
|
|||
imported_modules: Vec<String>,
|
||||
},
|
||||
|
||||
#[error("Unknown module field\n\n{name}\n\nin module\n\n{module_name}\n")]
|
||||
#[error("Unknown import '{name}' from module '{module_name}'\n")]
|
||||
#[diagnostic()]
|
||||
UnknownModuleField {
|
||||
#[label]
|
||||
location: Span,
|
||||
name: String,
|
||||
module_name: String,
|
||||
value_constructors: Vec<String>,
|
||||
type_constructors: Vec<String>,
|
||||
#[help]
|
||||
hint: Option<String>,
|
||||
},
|
||||
|
||||
#[error("Unknown module value\n\n{name}\n")]
|
||||
|
@ -419,6 +424,37 @@ impl Error {
|
|||
other => other,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unknown_module_field(
|
||||
location: Span,
|
||||
name: String,
|
||||
module_name: String,
|
||||
value_constructors: Vec<String>,
|
||||
type_constructors: Vec<String>,
|
||||
) -> Self {
|
||||
let mut candidates = vec![];
|
||||
candidates.extend(value_constructors);
|
||||
candidates.extend(type_constructors);
|
||||
|
||||
let hint = candidates
|
||||
.iter()
|
||||
.map(|s| (s, levenshtein::distance(&name, s)))
|
||||
.min_by(|(_, a), (_, b)| a.cmp(b))
|
||||
.and_then(|(suggestion, distance)| {
|
||||
if distance <= 5 {
|
||||
Some(format!("Did you mean to import '{suggestion}'?"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
Self::UnknownModuleField {
|
||||
location,
|
||||
name,
|
||||
module_name,
|
||||
hint,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, thiserror::Error, Diagnostic)]
|
||||
|
|
Loading…
Reference in New Issue