Refine types display.
This commit is contained in:
parent
58e1094b79
commit
86fc2f7bf1
@ -60,12 +60,12 @@ impl Engine {
|
||||
#[cfg(feature = "metadata")]
|
||||
let mut param_type_names: crate::StaticVec<_> = F::param_names()
|
||||
.iter()
|
||||
.map(|ty| format!("_: {}", self.map_type_name(ty)))
|
||||
.map(|ty| format!("_: {}", self.format_type_name(ty)))
|
||||
.collect();
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
if F::return_type() != TypeId::of::<()>() {
|
||||
param_type_names.push(self.map_type_name(F::return_type_name()).into());
|
||||
param_type_names.push(self.format_type_name(F::return_type_name()).into());
|
||||
}
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
@ -122,9 +122,9 @@ impl Engine {
|
||||
#[cfg(feature = "metadata")]
|
||||
let param_type_names: crate::StaticVec<_> = F::param_names()
|
||||
.iter()
|
||||
.map(|ty| format!("_: {}", self.map_type_name(ty)))
|
||||
.map(|ty| format!("_: {}", self.format_type_name(ty)))
|
||||
.chain(std::iter::once(
|
||||
self.map_type_name(F::return_type_name()).into(),
|
||||
self.format_type_name(F::return_type_name()).into(),
|
||||
))
|
||||
.collect();
|
||||
|
||||
|
@ -329,13 +329,47 @@ impl Engine {
|
||||
///
|
||||
/// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name],
|
||||
/// the type name provided for the registration will be used.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the type name is `&mut`.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn map_type_name<'a>(&'a self, name: &'a str) -> &'a str {
|
||||
self.type_names
|
||||
.get(name)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_else(|| map_std_type_name(name))
|
||||
.unwrap_or_else(|| map_std_type_name(name, true))
|
||||
}
|
||||
|
||||
/// Format a type name.
|
||||
///
|
||||
/// If a type is registered via [`register_type_with_name`][Engine::register_type_with_name],
|
||||
/// the type name provided for the registration will be used.
|
||||
#[cfg(feature = "metadata")]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn format_type_name<'a>(&'a self, name: &'a str) -> std::borrow::Cow<'a, str> {
|
||||
if name.starts_with("&mut ") {
|
||||
let x = &name[5..];
|
||||
let r = self.format_type_name(x);
|
||||
return if x != r {
|
||||
format!("&mut {}", r).into()
|
||||
} else {
|
||||
name.into()
|
||||
};
|
||||
}
|
||||
|
||||
self.type_names
|
||||
.get(name)
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_else(|| match name {
|
||||
"INT" => return type_name::<crate::INT>(),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
"FLOAT" => return type_name::<crate::FLOAT>(),
|
||||
_ => map_std_type_name(name, false),
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Make a `Box<`[`EvalAltResult<ErrorMismatchDataType>`][ERR::ErrorMismatchDataType]`>`.
|
||||
|
@ -968,18 +968,11 @@ impl Engine {
|
||||
_ if use_indexers => {
|
||||
let args = &mut [target, &mut idx];
|
||||
let hash_get = crate::ast::FnCallHashes::from_native(global.hash_idx_get());
|
||||
let fn_name = crate::engine::FN_IDX_GET;
|
||||
let pos = Position::NONE;
|
||||
|
||||
self.exec_fn_call(
|
||||
global,
|
||||
state,
|
||||
lib,
|
||||
crate::engine::FN_IDX_GET,
|
||||
hash_get,
|
||||
args,
|
||||
true,
|
||||
true,
|
||||
Position::NONE,
|
||||
None,
|
||||
level,
|
||||
global, state, lib, fn_name, hash_get, args, true, true, pos, None, level,
|
||||
)
|
||||
.map(|(v, _)| v.into())
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ macro_rules! def_register {
|
||||
// ^ function ABI type
|
||||
// ^ function parameter generic type name (A, B, C etc.)
|
||||
// ^ call argument(like A, *B, &mut C etc)
|
||||
// ^ function parameter marker type (T, Ref<T> or Mut<T>)
|
||||
// ^ function parameter actual type (T, &T or &mut T)
|
||||
// ^ function parameter marker type (A, Ref<B> or Mut<C>)
|
||||
// ^ function parameter actual type (A, &B or &mut C)
|
||||
// ^ argument let statement
|
||||
|
||||
impl<
|
||||
@ -117,7 +117,7 @@ macro_rules! def_register {
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<($($mark,)*), ()> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
|
||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||
@ -145,7 +145,7 @@ macro_rules! def_register {
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), ()> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RET>() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RET>() }
|
||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||
@ -173,7 +173,7 @@ macro_rules! def_register {
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<($($mark,)*), RhaiResultOf<RET>> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
|
||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||
@ -198,7 +198,7 @@ macro_rules! def_register {
|
||||
RET: Variant + Clone
|
||||
> RegisterNativeFunction<(NativeCallContext<'static>, $($mark,)*), RhaiResultOf<RET>> for FN {
|
||||
#[inline(always)] fn param_types() -> Box<[TypeId]> { vec![$(TypeId::of::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$par>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn param_names() -> Box<[&'static str]> { vec![$(std::any::type_name::<$param>()),*].into_boxed_slice() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type() -> TypeId { TypeId::of::<RhaiResultOf<RET>>() }
|
||||
#[cfg(feature = "metadata")] #[inline(always)] fn return_type_name() -> &'static str { std::any::type_name::<RhaiResultOf<RET>>() }
|
||||
#[inline(always)] fn into_callable_function(self) -> CallableFunction {
|
||||
|
@ -92,18 +92,60 @@ impl FuncInfo {
|
||||
/// `()` is cleared.
|
||||
/// [`RhaiResult`][crate::RhaiResult] and [`RhaiResultOf<T>`] are expanded.
|
||||
#[cfg(feature = "metadata")]
|
||||
pub fn format_return_type(typ: &str) -> std::borrow::Cow<str> {
|
||||
pub fn format_type(typ: &str, is_return_type: bool) -> std::borrow::Cow<str> {
|
||||
const RHAI_RESULT_TYPE: &str = "RhaiResult";
|
||||
const RHAI_RESULT_TYPE_EXPAND: &str = "Result<Dynamic, Box<EvalAltResult>>";
|
||||
const RHAI_RESULT_OF_TYPE: &str = "RhaiResultOf<";
|
||||
const RHAI_RESULT_OF_TYPE_EXPAND: &str = "Result<{}, Box<EvalAltResult>>";
|
||||
const RHAI_RANGE: &str = "ExclusiveRange";
|
||||
const RHAI_RANGE_TYPE: &str = "Range<";
|
||||
const RHAI_RANGE_EXPAND: &str = "Range<{}>";
|
||||
const RHAI_INCLUSIVE_RANGE: &str = "InclusiveRange";
|
||||
const RHAI_INCLUSIVE_RANGE_TYPE: &str = "RangeInclusive<";
|
||||
const RHAI_INCLUSIVE_RANGE_EXPAND: &str = "RangeInclusive<{}>";
|
||||
|
||||
let typ = typ.trim();
|
||||
|
||||
if typ.starts_with("rhai::") {
|
||||
return Self::format_type(&typ[6..], is_return_type);
|
||||
} else if typ.starts_with("&mut ") {
|
||||
let x = &typ[5..];
|
||||
let r = Self::format_type(x, false);
|
||||
return if r == x {
|
||||
typ.into()
|
||||
} else {
|
||||
format!("&mut {}", r).into()
|
||||
};
|
||||
}
|
||||
|
||||
match typ {
|
||||
"" | "()" => "".into(),
|
||||
"" | "()" if is_return_type => "".into(),
|
||||
"INT" => std::any::type_name::<crate::INT>().into(),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
"FLOAT" => std::any::type_name::<crate::FLOAT>().into(),
|
||||
RHAI_RANGE => RHAI_RANGE_EXPAND
|
||||
.replace("{}", std::any::type_name::<crate::INT>())
|
||||
.into(),
|
||||
RHAI_INCLUSIVE_RANGE => RHAI_INCLUSIVE_RANGE_EXPAND
|
||||
.replace("{}", std::any::type_name::<crate::INT>())
|
||||
.into(),
|
||||
RHAI_RESULT_TYPE => RHAI_RESULT_TYPE_EXPAND.into(),
|
||||
ty if ty.starts_with(RHAI_RANGE_TYPE) && ty.ends_with('>') => {
|
||||
let inner = &ty[RHAI_RANGE_TYPE.len()..ty.len() - 1];
|
||||
RHAI_RANGE_EXPAND
|
||||
.replace("{}", Self::format_type(inner, false).trim())
|
||||
.into()
|
||||
}
|
||||
ty if ty.starts_with(RHAI_INCLUSIVE_RANGE_TYPE) && ty.ends_with('>') => {
|
||||
let inner = &ty[RHAI_INCLUSIVE_RANGE_TYPE.len()..ty.len() - 1];
|
||||
RHAI_INCLUSIVE_RANGE_EXPAND
|
||||
.replace("{}", Self::format_type(inner, false).trim())
|
||||
.into()
|
||||
}
|
||||
ty if ty.starts_with(RHAI_RESULT_OF_TYPE) && ty.ends_with('>') => {
|
||||
let inner = &ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1];
|
||||
RHAI_RESULT_OF_TYPE_EXPAND
|
||||
.replace("{}", ty[RHAI_RESULT_OF_TYPE.len()..ty.len() - 1].trim())
|
||||
.replace("{}", Self::format_type(inner, false).trim())
|
||||
.into()
|
||||
}
|
||||
ty => ty.into(),
|
||||
@ -116,14 +158,27 @@ 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);
|
||||
let return_type = Self::format_type(&self.metadata.return_type, true);
|
||||
|
||||
if !self.metadata.params_info.is_empty() {
|
||||
let params: StaticVec<_> = self
|
||||
.metadata
|
||||
.params_info
|
||||
.iter()
|
||||
.map(|s| s.as_str())
|
||||
.map(|s| {
|
||||
let mut seg = s.splitn(2, ':');
|
||||
let name = match seg.next().unwrap().trim() {
|
||||
"" => "_",
|
||||
s => s,
|
||||
};
|
||||
let result: std::borrow::Cow<str> = match seg.next() {
|
||||
Some(typ) => {
|
||||
format!("{}: {}", name, FuncInfo::format_type(typ, false)).into()
|
||||
}
|
||||
None => name.into(),
|
||||
};
|
||||
result
|
||||
})
|
||||
.collect();
|
||||
sig.push_str(¶ms.join(", "));
|
||||
sig.push(')');
|
||||
|
@ -481,6 +481,12 @@ def_package! {
|
||||
// Register string iterator
|
||||
lib.set_iterator::<CharsStream>();
|
||||
|
||||
#[cfg(feature = "metadata")]
|
||||
let (range_type, range_inclusive_type) = (
|
||||
format!("range: Range<{}>", std::any::type_name::<INT>()),
|
||||
format!("range: RangeInclusive<{}>", std::any::type_name::<INT>()),
|
||||
);
|
||||
|
||||
let _hash = lib.set_native_fn("chars", |string, range: ExclusiveRange| {
|
||||
let from = INT::max(range.start, 0);
|
||||
let to = INT::max(range.end, from);
|
||||
@ -489,7 +495,7 @@ def_package! {
|
||||
#[cfg(feature = "metadata")]
|
||||
lib.update_fn_metadata_with_comments(
|
||||
_hash,
|
||||
["string: &str", "range: Range<INT>", "Iterator<Item=char>"],
|
||||
["string: &str", &range_type, "Iterator<Item=char>"],
|
||||
[
|
||||
"/// Return an iterator over an exclusive range of characters in the string.",
|
||||
"///",
|
||||
@ -511,7 +517,7 @@ def_package! {
|
||||
#[cfg(feature = "metadata")]
|
||||
lib.update_fn_metadata_with_comments(
|
||||
_hash,
|
||||
["string: &str", "range: RangeInclusive<INT>", "Iterator<Item=char>"],
|
||||
["string: &str", &range_inclusive_type, "Iterator<Item=char>"],
|
||||
[
|
||||
"/// Return an iterator over an inclusive range of characters in the string.",
|
||||
"///",
|
||||
@ -621,7 +627,7 @@ def_package! {
|
||||
#[cfg(feature = "metadata")]
|
||||
lib.update_fn_metadata_with_comments(
|
||||
_hash,
|
||||
["value: INT", "range: Range<INT>", "Iterator<Item=bool>"],
|
||||
["value: INT", &range_type, "Iterator<Item=bool>"],
|
||||
[
|
||||
"/// Return an iterator over an exclusive range of bits in the number.",
|
||||
"///",
|
||||
@ -645,7 +651,7 @@ def_package! {
|
||||
#[cfg(feature = "metadata")]
|
||||
lib.update_fn_metadata_with_comments(
|
||||
_hash,
|
||||
["value: INT", "range: RangeInclusive<INT>", "Iterator<Item=bool>"],
|
||||
["value: INT", &range_inclusive_type, "Iterator<Item=bool>"],
|
||||
[
|
||||
"/// Return an iterator over an inclusive range of bits in the number.",
|
||||
"///",
|
||||
@ -733,7 +739,7 @@ def_package! {
|
||||
#[cfg(feature = "metadata")]
|
||||
lib.update_fn_metadata_with_comments(
|
||||
_hash,
|
||||
["value: &mut INT", "range: Range<INT>", "Iterator<Item=bool>"],
|
||||
["value: &mut INT", "Iterator<Item=bool>"],
|
||||
[
|
||||
"/// Return an iterator over all the bits in the number.",
|
||||
"///",
|
||||
|
@ -7,7 +7,7 @@ use crate::{calc_fn_hash, Engine, AST};
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "no_std")]
|
||||
use std::prelude::v1::*;
|
||||
use std::{cmp::Ordering, collections::BTreeMap, iter::empty};
|
||||
use std::{borrow::Cow, cmp::Ordering, collections::BTreeMap, iter::empty};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -54,7 +54,7 @@ struct FnParam<'a> {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<&'a str>,
|
||||
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
|
||||
pub typ: Option<&'a str>,
|
||||
pub typ: Option<Cow<'a, str>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
|
||||
@ -125,12 +125,12 @@ impl<'a> From<&'a FuncInfo> for FnMetadata<'a> {
|
||||
"_" => None,
|
||||
s => Some(s),
|
||||
};
|
||||
let typ = seg.next().map(&str::trim);
|
||||
let typ = seg.next().map(|s| FuncInfo::format_type(s, false));
|
||||
FnParam { name, typ }
|
||||
})
|
||||
.collect(),
|
||||
_dummy: None,
|
||||
return_type: FuncInfo::format_return_type(&info.metadata.return_type).into_owned(),
|
||||
return_type: FuncInfo::format_type(&info.metadata.return_type, true).into_owned(),
|
||||
signature: info.gen_signature(),
|
||||
doc_comments: if info.func.is_script() {
|
||||
#[cfg(feature = "no_function")]
|
||||
|
@ -546,44 +546,66 @@ impl Hash for Dynamic {
|
||||
/// Map the name of a standard type into a friendly form.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn map_std_type_name(name: &str) -> &str {
|
||||
pub(crate) fn map_std_type_name(name: &str, shorthands: bool) -> &str {
|
||||
let name = name.trim();
|
||||
|
||||
if name.starts_with("rhai::") {
|
||||
return map_std_type_name(&name[6..], shorthands);
|
||||
}
|
||||
|
||||
if name == type_name::<String>() {
|
||||
return "string";
|
||||
return if shorthands { "string" } else { "String" };
|
||||
}
|
||||
if name == type_name::<ImmutableString>() {
|
||||
return "string";
|
||||
return if shorthands {
|
||||
"string"
|
||||
} else {
|
||||
"ImmutableString"
|
||||
};
|
||||
}
|
||||
if name == type_name::<&str>() {
|
||||
return "string";
|
||||
}
|
||||
if name == type_name::<FnPtr>() {
|
||||
return "Fn";
|
||||
return if shorthands { "string" } else { "&str" };
|
||||
}
|
||||
#[cfg(feature = "decimal")]
|
||||
if name == type_name::<rust_decimal::Decimal>() {
|
||||
return "decimal";
|
||||
return if shorthands { "decimal" } else { "Decimal" };
|
||||
}
|
||||
if name == type_name::<FnPtr>() {
|
||||
return if shorthands { "Fn" } else { "FnPtr" };
|
||||
}
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if name == type_name::<crate::Array>() {
|
||||
return "array";
|
||||
return if shorthands { "array" } else { "Array" };
|
||||
}
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
if name == type_name::<crate::Blob>() {
|
||||
return "blob";
|
||||
return if shorthands { "blob" } else { "Blob" };
|
||||
}
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
if name == type_name::<crate::Map>() {
|
||||
return "map";
|
||||
return if shorthands { "map" } else { "Map" };
|
||||
}
|
||||
#[cfg(not(feature = "no_std"))]
|
||||
if name == type_name::<Instant>() {
|
||||
return "timestamp";
|
||||
return if shorthands { "timestamp" } else { "Instant" };
|
||||
}
|
||||
if name == type_name::<ExclusiveRange>() {
|
||||
return "range";
|
||||
if name == type_name::<ExclusiveRange>() || name == "ExclusiveRange" {
|
||||
return if shorthands {
|
||||
"range"
|
||||
} else if cfg!(feature = "only_i32") {
|
||||
"Range<i32>"
|
||||
} else {
|
||||
"Range<i64>"
|
||||
};
|
||||
}
|
||||
if name == type_name::<InclusiveRange>() {
|
||||
return "range=";
|
||||
if name == type_name::<InclusiveRange>() || name == "InclusiveRange" {
|
||||
return if shorthands {
|
||||
"range="
|
||||
} else if cfg!(feature = "only_i32") {
|
||||
"RangeInclusive<i32>"
|
||||
} else {
|
||||
"RangeInclusive<i64>"
|
||||
};
|
||||
}
|
||||
|
||||
name
|
||||
|
Loading…
Reference in New Issue
Block a user