mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 22:58:11 +08:00
New error message
This commit is contained in:
@@ -539,50 +539,56 @@ impl ProtoNetwork {
|
|||||||
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum GraphErrorType {
|
pub enum GraphErrorType {
|
||||||
NodeNotFound(NodeId),
|
NodeNotFound(NodeId),
|
||||||
UnexpectedGenerics { index: usize, inputs: Vec<Type> },
|
UnexpectedGenerics {
|
||||||
|
index: usize,
|
||||||
|
inputs: Vec<Type>,
|
||||||
|
},
|
||||||
NoImplementations,
|
NoImplementations,
|
||||||
NoConstructor,
|
NoConstructor,
|
||||||
InvalidImplementations { inputs: String, error_inputs: Vec<Vec<(usize, (Type, Type))>> },
|
// The first vec represents a list of correct NodeIOTypes
|
||||||
MultipleImplementations { inputs: String, valid: Vec<NodeIOTypes> },
|
// The second vec represents what the input index and what it expects
|
||||||
|
InvalidImplementations {
|
||||||
|
identifier: ProtoNodeIdentifier,
|
||||||
|
inputs: String,
|
||||||
|
error_inputs: Vec<Vec<(usize, Type)>>,
|
||||||
|
},
|
||||||
|
MultipleImplementations {
|
||||||
|
inputs: String,
|
||||||
|
valid: Vec<NodeIOTypes>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
impl Debug for GraphErrorType {
|
impl Debug for GraphErrorType {
|
||||||
// TODO: format with the document graph context so the input index is the same as in the graph UI.
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
GraphErrorType::NodeNotFound(id) => write!(f, "Input node {id} is not present in the typing context"),
|
GraphErrorType::NodeNotFound(id) => write!(f, "Input node {id} is not present in the typing context"),
|
||||||
GraphErrorType::UnexpectedGenerics { index, inputs } => write!(f, "Generic inputs should not exist but found at {index}: {inputs:?}"),
|
GraphErrorType::UnexpectedGenerics { index, inputs } => write!(f, "Generic inputs should not exist but found at {index}: {inputs:?}"),
|
||||||
GraphErrorType::NoImplementations => write!(f, "No implementations found"),
|
GraphErrorType::NoImplementations => write!(f, "No implementations found"),
|
||||||
GraphErrorType::NoConstructor => write!(f, "No construct found for node"),
|
GraphErrorType::NoConstructor => write!(f, "No construct found for node"),
|
||||||
GraphErrorType::InvalidImplementations { inputs, error_inputs } => {
|
GraphErrorType::InvalidImplementations { identifier, inputs, error_inputs } => {
|
||||||
let format_error = |(index, (found, expected)): &(usize, (Type, Type))| {
|
let plural = if error_inputs.first().is_some_and(|first| first.len() > 1) { "s" } else { "" }.to_string();
|
||||||
let index = index + 1;
|
let solutions = error_inputs
|
||||||
format!(
|
.iter()
|
||||||
"\
|
.map(|expected_inputs| {
|
||||||
• Input {index}:\n\
|
expected_inputs
|
||||||
…found: {found}\n\
|
.iter()
|
||||||
…expected: {expected}\
|
.enumerate()
|
||||||
"
|
.map(|(error_index, (input_index, expected_type))| {
|
||||||
)
|
let pre_text = if error_index == 0 { "• " } else { " " };
|
||||||
};
|
format!("{}Input {} expected: {}\n", pre_text, input_index + 1, expected_type)
|
||||||
let format_error_list = |errors: &Vec<(usize, (Type, Type))>| errors.iter().map(format_error).collect::<Vec<_>>().join("\n");
|
})
|
||||||
let mut errors = error_inputs.iter().map(format_error_list).collect::<Vec<_>>();
|
.collect::<String>()
|
||||||
errors.sort();
|
})
|
||||||
let errors = errors.join("\n");
|
.collect::<Vec<_>>()
|
||||||
let incompatibility = if errors.chars().filter(|&c| c == '•').count() == 1 {
|
.join("\n");
|
||||||
"This input type is incompatible:"
|
let node_name = identifier.name.to_string();
|
||||||
} else {
|
|
||||||
"These input types are incompatible:"
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"\
|
"Potential solutions for invalid input{plural}:\n\
|
||||||
{incompatibility}\n\
|
{solutions}\n\
|
||||||
{errors}\n\
|
The node is currently receiving the following input types:\n\
|
||||||
\n\
|
{inputs}\n\n\
|
||||||
The node is currently receiving all of the following input types:\n\
|
This is not a supported arrangement of types for:\n\
|
||||||
{inputs}\n\
|
{node_name}\
|
||||||
This is not a supported arrangement of types for the node.\
|
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -766,10 +772,7 @@ impl TypingContext {
|
|||||||
.zip([&node_io.call_argument].into_iter().chain(&node_io.inputs).cloned())
|
.zip([&node_io.call_argument].into_iter().chain(&node_io.inputs).cloned())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(_, (p1, p2))| !valid_type(p1, p2))
|
.filter(|(_, (p1, p2))| !valid_type(p1, p2))
|
||||||
.map(|(index, ty)| {
|
.map(|(index, (_, expected))| (index - 1, expected))
|
||||||
let i = node.original_location.inputs(index).min_by_key(|s| s.node.len()).map(|s| s.index).unwrap_or(index);
|
|
||||||
(i, ty)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if current_errors.len() < best_errors {
|
if current_errors.len() < best_errors {
|
||||||
best_errors = current_errors.len();
|
best_errors = current_errors.len();
|
||||||
@@ -779,14 +782,16 @@ impl TypingContext {
|
|||||||
error_inputs.push(current_errors);
|
error_inputs.push(current_errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let inputs = [call_argument]
|
|
||||||
.into_iter()
|
let inputs = inputs.into_iter().enumerate().map(|(i, t)| format!("• Input {}: {}", i + 1, t)).collect::<Vec<_>>().join("\n");
|
||||||
.chain(&inputs)
|
Err(vec![GraphError::new(
|
||||||
.enumerate()
|
node,
|
||||||
.filter_map(|(i, t)| if i == 0 { None } else { Some(format!("• Input {i}: {t}")) })
|
GraphErrorType::InvalidImplementations {
|
||||||
.collect::<Vec<_>>()
|
identifier: node.identifier.clone(),
|
||||||
.join("\n");
|
inputs,
|
||||||
Err(vec![GraphError::new(node, GraphErrorType::InvalidImplementations { inputs, error_inputs })])
|
error_inputs,
|
||||||
|
},
|
||||||
|
)])
|
||||||
}
|
}
|
||||||
[(node_io, org_nio)] => {
|
[(node_io, org_nio)] => {
|
||||||
let node_io = node_io.clone();
|
let node_io = node_io.clone();
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ impl std::fmt::Debug for Type {
|
|||||||
Self::Concrete(ty) => format!("Concrete<{}, {:?}>", ty.name, ty.id),
|
Self::Concrete(ty) => format!("Concrete<{}, {:?}>", ty.name, ty.id),
|
||||||
#[cfg(not(feature = "type_id_logging"))]
|
#[cfg(not(feature = "type_id_logging"))]
|
||||||
Self::Concrete(ty) => format_type(&ty.name),
|
Self::Concrete(ty) => format_type(&ty.name),
|
||||||
Self::Fn(call_arg, return_value) => format!("{return_value:?} called with {call_arg:?}"),
|
Self::Fn(_, return_value) => format!("{return_value:?}"),
|
||||||
Self::Future(ty) => format!("{ty:?}"),
|
Self::Future(ty) => format!("{ty:?}"),
|
||||||
};
|
};
|
||||||
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
||||||
@@ -382,7 +382,7 @@ impl std::fmt::Display for Type {
|
|||||||
let result = match self {
|
let result = match self {
|
||||||
Type::Generic(name) => name.to_string(),
|
Type::Generic(name) => name.to_string(),
|
||||||
Type::Concrete(ty) => format_type(&ty.name),
|
Type::Concrete(ty) => format_type(&ty.name),
|
||||||
Type::Fn(call_arg, return_value) => format!("{return_value} called with {call_arg}"),
|
Type::Fn(_, return_value) => format!("{return_value}"),
|
||||||
Type::Future(ty) => ty.to_string(),
|
Type::Future(ty) => ty.to_string(),
|
||||||
};
|
};
|
||||||
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
||||||
|
|||||||
Reference in New Issue
Block a user