diff --git a/CHANGELOG.md b/CHANGELOG.md index b8374485..edf84e76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ Bug fixes * `set_bit` for bit-flags with negative index now works correctly. * Misnamed `params` field `name` in the JSON output of `Engine::gen_fn_metadata_to_json` is fixed (was incorrectly named `type`). +Enhancements +------------ + +* Formatting of return types in functions metadata info is improved. + Version 1.4.0 ============= diff --git a/src/module/mod.rs b/src/module/mod.rs index 60dfb65b..b21d93c2 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -87,6 +87,27 @@ pub struct FuncInfo { } impl FuncInfo { + /// Format a return type to be display-friendly. + /// + /// `()` is cleared. + /// [`RhaiResult`][crate::RhaiResult] and [`RhaiResultOf`] are expanded. + pub fn format_return_type(typ: &str) -> std::borrow::Cow { + const RHAI_RESULT_TYPE: &str = "RhaiResult"; + const RHAI_RESULT_TYPE_EXPAND: &str = "Result>"; + const RHAI_RESULT_OF_TYPE: &str = "RhaiResultOf<"; + const RHAI_RESULT_OF_TYPE_EXPAND: &str = "Result<{}, Box>"; + + match typ { + "" | "()" => "".into(), + RHAI_RESULT_TYPE => RHAI_RESULT_TYPE_EXPAND.into(), + ty if ty.starts_with(RHAI_RESULT_OF_TYPE) && ty.ends_with(">") => { + RHAI_RESULT_OF_TYPE_EXPAND + .replace("{}", ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1].trim()) + .into() + } + ty => ty.into(), + } + } /// Generate a signature of the function. /// Exported under the `metadata` feature only. #[cfg(feature = "metadata")] @@ -94,6 +115,8 @@ impl FuncInfo { pub fn gen_signature(&self) -> String { let mut sig = format!("{}(", self.metadata.name); + let return_type = Self::format_return_type(&self.metadata.return_type); + if !self.metadata.params_info.is_empty() { let params: StaticVec<_> = self .metadata @@ -102,14 +125,11 @@ impl FuncInfo { .map(|s| s.as_str()) .collect(); sig.push_str(¶ms.join(", ")); - sig.push_str(")"); + sig.push(')'); - match self.metadata.return_type.as_str() { - "" | "()" => (), - ty => { - sig.push_str(" -> "); - sig.push_str(ty); - } + if !return_type.is_empty() { + sig.push_str(" -> "); + sig.push_str(&return_type); } } else { for x in 0..self.metadata.params { @@ -119,14 +139,14 @@ impl FuncInfo { } } - if self.func.is_script() { - sig.push(')'); - } else { - sig.push_str(")"); + sig.push(')'); - match self.metadata.return_type.as_str() { - "()" => (), - _ => sig.push_str(" -> ?"), + if !self.func.is_script() { + sig.push(')'); + + if !return_type.is_empty() { + sig.push_str(" -> "); + sig.push_str(&return_type); } } } diff --git a/src/serde/metadata.rs b/src/serde/metadata.rs index fd2f7df0..3ccadfb3 100644 --- a/src/serde/metadata.rs +++ b/src/serde/metadata.rs @@ -70,8 +70,11 @@ struct FnMetadata<'a> { pub num_params: usize, #[serde(default, skip_serializing_if = "Vec::is_empty")] pub params: Vec>, + // No idea why the following is needed otherwise serde comes back with a lifetime error #[serde(default, skip_serializing_if = "Option::is_none")] - pub return_type: Option<&'a str>, + pub _dummy: Option<&'a str>, + #[serde(default, skip_serializing_if = "String::is_empty")] + pub return_type: String, pub signature: String, #[serde(default, skip_serializing_if = "Vec::is_empty")] pub doc_comments: Vec<&'a str>, @@ -126,10 +129,8 @@ impl<'a> From<&'a FuncInfo> for FnMetadata<'a> { FnParam { name, typ } }) .collect(), - return_type: match info.metadata.return_type.as_str() { - "" | "()" => None, - ty => Some(ty), - }, + _dummy: None, + return_type: FuncInfo::format_return_type(&info.metadata.return_type).into_owned(), signature: info.gen_signature(), doc_comments: if info.func.is_script() { #[cfg(feature = "no_function")]