mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 05:43:53 +01:00
add warning to if-statement in check mode
warning is shown if the condition of an if statement can never be true or false, and the user used the check command. warnings are not shown when you use `mers run`.
This commit is contained in:
parent
385019e43c
commit
817ed25f96
@ -125,7 +125,8 @@ fn main() {
|
||||
exit(20);
|
||||
}
|
||||
Ok(parsed) => {
|
||||
let (i1, _, i3) = config.infos();
|
||||
let (i1, _, mut i3) = config.infos();
|
||||
i3.global.show_warnings_to_stderr();
|
||||
match compile(&*parsed, i1) {
|
||||
Err(e) => {
|
||||
eprintln!("{e:?}");
|
||||
|
@ -97,6 +97,8 @@ pub enum EColor {
|
||||
MaximumRuntimeExceeded,
|
||||
|
||||
InCodePositionLine,
|
||||
|
||||
Warning,
|
||||
}
|
||||
|
||||
pub trait ETheme: ThemeGen<C = EColor, T = String> {}
|
||||
|
@ -42,6 +42,10 @@ pub fn default_theme<C>(
|
||||
_ => return None,
|
||||
});
|
||||
}
|
||||
if let Warning = color {
|
||||
// same color as runtime errors, because warnings are only displayed in `check` mode, where the program won't run.
|
||||
return Some(yellow);
|
||||
}
|
||||
let hard_err = red;
|
||||
let type_right = blue;
|
||||
let type_wrong = magenta;
|
||||
@ -56,7 +60,7 @@ pub fn default_theme<C>(
|
||||
drop(cyan_bright);
|
||||
use EColor::*;
|
||||
Some(match color {
|
||||
Indent(_) => unreachable!(),
|
||||
Indent(_) | Warning => unreachable!(),
|
||||
|
||||
// macros (#...)
|
||||
WhitespaceAfterHashtag
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
data::{self, tuple::TupleT, Data, MersType, Type},
|
||||
data::{self, tuple::TupleT, Data, Type},
|
||||
errors::{CheckError, EColor, SourceRange},
|
||||
};
|
||||
|
||||
@ -47,18 +47,44 @@ impl MersStatement for If {
|
||||
),
|
||||
]));
|
||||
}
|
||||
let mut t = if Type::new(data::bool::TrueT).is_included_in(&cond_return_type) {
|
||||
let may_be_true = Type::new(data::bool::TrueT).is_included_in(&cond_return_type);
|
||||
let may_be_false = Type::new(data::bool::FalseT).is_included_in(&cond_return_type);
|
||||
let mut t = if may_be_true {
|
||||
self.on_true.check(info, None)?
|
||||
} else {
|
||||
Type::empty()
|
||||
};
|
||||
if Type::new(data::bool::FalseT).is_included_in(&cond_return_type) {
|
||||
if may_be_false {
|
||||
if let Some(f) = &self.on_false {
|
||||
t.add_all(&f.check(info, None)?);
|
||||
} else {
|
||||
t.add(Arc::new(TupleT(vec![])));
|
||||
}
|
||||
}
|
||||
if let Some(show_warning) = &info.global.show_warnings {
|
||||
if !may_be_false || !may_be_true {
|
||||
let mut e = CheckError::new().src(vec![
|
||||
(self.pos_in_src.clone(), None),
|
||||
(
|
||||
self.condition.source_range(),
|
||||
Some(EColor::IfConditionNotBool),
|
||||
),
|
||||
]);
|
||||
if !may_be_true {
|
||||
e.msg_mut(vec![(
|
||||
"Condition in this if-statement is never true".to_owned(),
|
||||
Some(EColor::Warning),
|
||||
)]);
|
||||
}
|
||||
if !may_be_false {
|
||||
e.msg_mut(vec![(
|
||||
"Condition in this if-statement is never false".to_owned(),
|
||||
Some(EColor::Warning),
|
||||
)]);
|
||||
}
|
||||
show_warning(e);
|
||||
}
|
||||
}
|
||||
Ok(t)
|
||||
}
|
||||
fn run_custom(&self, info: &mut super::Info) -> Result<Data, CheckError> {
|
||||
|
@ -142,10 +142,11 @@ pub struct CheckLocal {
|
||||
>,
|
||||
>,
|
||||
}
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct CheckLocalGlobalInfo {
|
||||
pub depth: usize,
|
||||
pub enable_hooks: bool,
|
||||
pub show_warnings: Option<Arc<dyn Fn(CheckError) + Send + Sync>>,
|
||||
/// ((results, byte_pos_in_src, deepest_statement))
|
||||
/// you only have to set `byte_pos_in_src`. `deepest` is used internally.
|
||||
/// These values should be initialized to `(vec![], _, 0)`, but `0` can be replaced by a minimum statement depth, i.e. `2` to exclude the outer scope (which has depth `1`).
|
||||
@ -160,6 +161,22 @@ pub struct CheckLocalGlobalInfo {
|
||||
>,
|
||||
pub unused_try_statements: Arc<Mutex<Vec<(SourceRange, Vec<Option<SourceRange>>)>>>,
|
||||
}
|
||||
impl CheckLocalGlobalInfo {
|
||||
pub fn show_warnings_to_stderr(&mut self) {
|
||||
self.show_warnings = Some(Arc::new(|e| {
|
||||
#[cfg(feature = "ecolor-term")]
|
||||
let theme = crate::errors::themes::TermDefaultTheme;
|
||||
#[cfg(not(feature = "ecolor-term"))]
|
||||
let theme = crate::errors::themes::NoTheme;
|
||||
eprintln!("{}", e.display(theme));
|
||||
}));
|
||||
}
|
||||
}
|
||||
impl Debug for CheckLocalGlobalInfo {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "CheckLocalGlobalInfo {{ depth: {}, enable_hooks: {}, show_warnings: {}, unused_try_statements: {} }}", self.depth, self.enable_hooks, self.show_warnings.is_some(), self.unused_try_statements.lock().unwrap().len())
|
||||
}
|
||||
}
|
||||
impl Debug for CheckLocal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "CheckLocal {:?}, {:?}", self.vars, self.types.keys())
|
||||
|
Loading…
Reference in New Issue
Block a user