Normalize identifiers to - instead of _

As a result
 - The error messages will now show the error with `-` instead of `_`
 - The LSP will auto-complete with -
 - The interpreter's list of properties will list the property with '-'
   (but we made the change so that set_property, get_property, and so on
   work also if passed a '-')
This commit is contained in:
Olivier Goffart 2021-08-10 18:03:59 +02:00 committed by Olivier Goffart
parent 9c95da8a7c
commit c25538c982
49 changed files with 327 additions and 272 deletions

View file

@ -77,18 +77,18 @@ interface Callback {
require.extensions['.60'] =
function (module, filename) {
var c = native.load(filename);
module.exports[c.name()] = function (init_properties: any) {
module.exports[c.name().replaceAll('-', '_')] = function (init_properties: any) {
let comp = c.create(init_properties);
let ret = new Component(comp);
c.properties().forEach((x: string) => {
Object.defineProperty(ret, x, {
Object.defineProperty(ret, x.replaceAll('-', '_'), {
get() { return comp.get_property(x); },
set(newValue) { comp.set_property(x, newValue); },
enumerable: true,
})
});
c.callbacks().forEach((x: string) => {
Object.defineProperty(ret, x, {
Object.defineProperty(ret, x.replaceAll('-', '_'), {
get() {
let callback = function () { return comp.invoke_callback(x, [...arguments]); } as Callback;
callback.setHandler = function (callback) { comp.connect_callback(x, callback) };

View file

@ -119,7 +119,7 @@ fn create<'cx>(
let properties =
component_type.properties_and_callbacks().collect::<std::collections::HashMap<_, _>>();
for x in args.get_own_property_names(cx)?.to_vec(cx)? {
let prop_name = x.to_string(cx)?.value();
let prop_name = x.to_string(cx)?.value().replace('_', "-");
let value = args.get(cx, x)?;
let ty = properties
.get(&prop_name)
@ -212,7 +212,7 @@ fn to_eval_value<'cx>(
Ok((
pro_name.clone(),
to_eval_value(
obj.get(cx, pro_name.as_str())?,
obj.get(cx, pro_name.replace('-', "_").as_str())?,
pro_ty.clone(),
cx,
persistent_context,
@ -271,7 +271,7 @@ fn to_js_value<'cx>(
let js_object = JsObject::new(cx);
for (k, e) in o.iter() {
let v = to_js_value(e.clone(), cx)?;
js_object.set(cx, k, v)?;
js_object.set(cx, k.replace('-', "_").as_str(), v)?;
}
js_object.as_value(cx)
}

View file

@ -229,9 +229,18 @@ use crate::object_tree::{
};
use cpp_ast::*;
use itertools::Itertools;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::rc::Rc;
fn ident(ident: &str) -> Cow<'_, str> {
if ident.contains('-') {
ident.replace('-', "_").into()
} else {
ident.into()
}
}
impl CppType for Type {
fn cpp_type(&self) -> Option<String> {
match self {
@ -246,9 +255,9 @@ impl CppType for Type {
Type::LogicalLength => Some("float".to_owned()),
Type::Percent => Some("float".to_owned()),
Type::Bool => Some("bool".to_owned()),
Type::Struct { name: Some(name), node: Some(_), .. } => Some(name.clone()),
Type::Struct { name: Some(name), node: Some(_), .. } => Some(ident(name).into_owned()),
Type::Struct { name: Some(name), node: None, .. } => {
Some(format!("sixtyfps::cbindgen_private::{}", name))
Some(format!("sixtyfps::cbindgen_private::{}", ident(name)))
}
Type::Struct { fields, .. } => {
let elem = fields.values().map(|v| v.cpp_type()).collect::<Option<Vec<_>>>()?;
@ -260,7 +269,7 @@ impl CppType for Type {
Type::Image => Some("sixtyfps::Image".to_owned()),
Type::Builtin(elem) => elem.native_class.cpp_type.clone(),
Type::Enumeration(enumeration) => {
Some(format!("sixtyfps::cbindgen_private::{}", enumeration.name))
Some(format!("sixtyfps::cbindgen_private::{}", ident(&enumeration.name)))
}
Type::Brush => Some("sixtyfps::Brush".to_owned()),
Type::LayoutCache => Some("sixtyfps::SharedVector<float>".into()),
@ -301,7 +310,7 @@ fn new_struct_with_bindings(
.iter()
.map(|(prop, initializer)| {
let initializer = compile_expression(initializer, component);
format!("var.{} = {};", prop, initializer)
format!("var.{} = {};", ident(prop), initializer)
})
.collect();
@ -358,10 +367,10 @@ fn handle_property_binding(
} else if item.is_flickable_viewport {
format!(
"{id}.viewport.",
id = crate::object_tree::find_parent_element(elem).unwrap().borrow().id
id = ident(&crate::object_tree::find_parent_element(elem).unwrap().borrow().id)
)
} else {
format!("{id}.", id = item.id)
format!("{id}.", id = ident(&item.id))
};
let prop_type = item.lookup_property(prop_name).property_type;
if let Type::Callback { args, .. } = &prop_type {
@ -376,7 +385,7 @@ fn handle_property_binding(
return {code};
}});",
accessor_prefix = accessor_prefix,
prop = prop_name,
prop = ident(prop_name),
params = params.join(", "),
code = compile_expression_wrap_return(binding_expression, &component)
));
@ -401,7 +410,7 @@ fn handle_property_binding(
let component = &item.enclosing_component.upgrade().unwrap();
let init_expr = compile_expression_wrap_return(binding_expression, component);
let cpp_prop = format!("{}{}", accessor_prefix, prop_name);
let cpp_prop = format!("{}{}", accessor_prefix, ident(prop_name));
init.push(if is_constant {
format!("{}.set({});", cpp_prop, init_expr)
@ -466,8 +475,11 @@ fn handle_item(elem: &ElementRc, main_struct: &mut Struct) {
main_struct.members.push((
Access::Private,
Declaration::Var(Var {
ty: format!("sixtyfps::cbindgen_private::{}", item.base_type.as_native().class_name),
name: item.id.clone(),
ty: format!(
"sixtyfps::cbindgen_private::{}",
ident(&item.base_type.as_native().class_name)
),
name: ident(&item.id).into_owned(),
init: Some("{}".to_owned()),
}),
));
@ -486,7 +498,7 @@ fn handle_repeater(
diag: &mut BuildDiagnostics,
) {
let parent_element = base_component.parent_element.upgrade().unwrap();
let repeater_id = format!("repeater_{}", parent_element.borrow().id);
let repeater_id = format!("repeater_{}", ident(&parent_element.borrow().id));
let mut model = compile_expression(&repeated.model, parent_component);
if repeated.is_conditional_element {
@ -609,7 +621,7 @@ fn generate_struct(
.iter()
.map(|(name, t)| {
use std::fmt::Write;
write!(operator_eq, " && a.{0} == b.{0}", name).unwrap();
write!(operator_eq, " && a.{0} == b.{0}", ident(name)).unwrap();
(
Access::Public,
Declaration::Var(Var {
@ -620,7 +632,7 @@ fn generate_struct(
);
Default::default()
}),
name: name.clone(),
name: ident(name).into_owned(),
..Default::default()
}),
)
@ -681,7 +693,8 @@ fn generate_component(
let is_root = component.parent_element.upgrade().is_none();
let mut init = vec!["[[maybe_unused]] auto self = this;".into()];
for (cpp_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
for (prop_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
let cpp_name = ident(&prop_name);
let access = if let Some(alias) = &property_decl.is_alias {
access_named_reference(alias, component, "this")
} else {
@ -750,7 +763,7 @@ fn generate_component(
let set_value = if let Some(alias) = &property_decl.is_alias {
property_set_value_code(component, &alias.element(), alias.name(), "value")
} else {
property_set_value_code(component, &component.root_element, cpp_name, "value")
property_set_value_code(component, &component.root_element, prop_name, "value")
};
let prop_setter: Vec<String> = vec![
@ -773,7 +786,7 @@ fn generate_component(
if property_decl.is_alias.is_none() {
component_struct.members.push((
if component.is_global() { Access::Public } else { Access::Private },
Declaration::Var(Var { ty, name: cpp_name.clone(), init: None }),
Declaration::Var(Var { ty, name: cpp_name.into_owned(), init: None }),
));
}
}
@ -1057,7 +1070,7 @@ fn generate_component(
tree_array.push(format!(
"sixtyfps::private_api::make_item_node(offsetof({}, {}) + offsetof(sixtyfps::cbindgen_private::Flickable, viewport), SIXTYFPS_GET_ITEM_VTABLE(RectangleVTable), {}, {}, {})",
&component_id,
crate::object_tree::find_parent_element(item_rc).unwrap().borrow().id,
ident(&crate::object_tree::find_parent_element(item_rc).unwrap().borrow().id),
item.children.len(),
children_offset,
parent_index,
@ -1066,7 +1079,7 @@ fn generate_component(
tree_array.push(format!(
"sixtyfps::private_api::make_item_node(offsetof({}, {}), {}, {}, {}, {})",
component_id,
item.id,
ident(&item.id),
item.base_type.as_native().cpp_vtable_getter,
item.children.len(),
children_offset,
@ -1074,8 +1087,10 @@ fn generate_component(
));
}
handle_item(item_rc, &mut component_struct);
item_names_and_vt_symbols
.push((item.id.clone(), item.base_type.as_native().cpp_vtable_getter.clone()));
item_names_and_vt_symbols.push((
ident(&item.id).into_owned(),
item.base_type.as_native().cpp_vtable_getter.clone(),
));
}
});
@ -1261,7 +1276,7 @@ fn generate_component(
statements: Some(vec![format!(
"return {{ {vt}, const_cast<decltype(this->{id})*>(&this->{id}) }};",
vt = root_elem.base_type.as_native().cpp_vtable_getter,
id = root_elem.id
id = ident(&root_elem.id)
)]),
..Default::default()
}),
@ -1303,11 +1318,11 @@ fn generate_component(
fn component_id(component: &Rc<Component>) -> String {
if component.is_global() {
component.root_element.borrow().id.clone()
ident(&component.root_element.borrow().id).into_owned()
} else if component.id.is_empty() {
format!("Component_{}", component.root_element.borrow().id)
format!("Component_{}", ident(&component.root_element.borrow().id))
} else {
component.id.clone()
ident(&component.id).into_owned()
}
}
@ -1351,16 +1366,16 @@ fn access_member(
let enclosing_component = e.enclosing_component.upgrade().unwrap();
if Rc::ptr_eq(component, &enclosing_component) {
if e.property_declarations.contains_key(name) || name.is_empty() || component.is_global() {
format!("{}->{}", component_cpp, name)
format!("{}->{}", component_cpp, ident(name))
} else if e.is_flickable_viewport {
format!(
"{}->{}.viewport.{}",
component_cpp,
crate::object_tree::find_parent_element(element).unwrap().borrow().id,
name
ident(&crate::object_tree::find_parent_element(element).unwrap().borrow().id),
ident(name)
)
} else {
format!("{}->{}.{}", component_cpp, e.id.as_str(), name)
format!("{}->{}.{}", component_cpp, ident(&e.id), ident(name))
}
} else if enclosing_component.is_global() {
let mut root_component = component.clone();
@ -1506,9 +1521,9 @@ fn compile_expression(
}
Expression::FunctionParameterReference { index, .. } => format!("arg_{}", index),
Expression::StoreLocalVariable { name, value } => {
format!("auto {} = {};", name, compile_expression(value, component))
format!("auto {} = {};", ident(name), compile_expression(value, component))
}
Expression::ReadLocalVariable { name, .. } => name.clone(),
Expression::ReadLocalVariable { name, .. } => ident(name).into_owned(),
Expression::StructFieldAccess { base, name } => match base.ty() {
Type::Struct { fields, name : None, .. } => {
let index = fields
@ -1518,7 +1533,7 @@ fn compile_expression(
format!("std::get<{}>({})", index, compile_expression(base, component))
}
Type::Struct{..} => {
format!("{}.{}", compile_expression(base, component), name)
format!("{}.{}", compile_expression(base, component), ident(name))
}
_ => panic!("Expression::ObjectAccess's base expression is not an Object type"),
},
@ -1611,7 +1626,7 @@ fn compile_expression(
format!("{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &m_window.window_handle())",
vt = native_item.cpp_vtable_getter,
ty = native_item.class_name,
id = item.id,
id = ident(&item.id),
o = to_cpp_orientation(*orientation),
)
} else {
@ -1706,7 +1721,7 @@ fn compile_expression(
.unwrap_or_else(|| "(Error: missing member in object)".to_owned())
});
if let Some(name) = name {
format!("{}{{{}}}", name, elem.join(", "))
format!("{}{{{}}}", ident(name), elem.join(", "))
} else {
format!("std::make_tuple({})", elem.join(", "))
}
@ -1733,7 +1748,7 @@ fn compile_expression(
)
}
Expression::EnumerationValue(value) => {
format!("sixtyfps::cbindgen_private::{}::{}", value.enumeration.name, value.to_string())
format!("sixtyfps::cbindgen_private::{}::{}", value.enumeration.name, ident(&value.to_string()))
}
Expression::ReturnStatement(Some(expr)) => format!(
"throw sixtyfps::private_api::ReturnWrapper<{}>({})",
@ -1870,7 +1885,7 @@ fn compile_assignment(
.expect("Expression::ObjectAccess: Cannot find a key in an object");
format!("std::get<{}>({})", index, tmpobj)
}
Type::Struct { .. } => format!("{}.{}", tmpobj, name),
Type::Struct { .. } => format!("{}.{}", tmpobj, ident(name)),
_ => panic!("Expression::ObjectAccess's base expression is not an Object type"),
};
let op = if op == '=' { ' ' } else { op };
@ -1902,7 +1917,7 @@ fn compile_assignment(
"self",
);
let index_access = access_member(&parent_component.root_element, "", component, "self");
let repeater_id = format!("repeater_{}", element.borrow().id);
let repeater_id = format!("repeater_{}", ident(&element.borrow().id));
if op == '=' {
format!(
"{}{}.model_set_row_data({}index.get(), {})",
@ -1983,14 +1998,16 @@ fn box_layout_data(
let mut repeater_idx = 0usize;
for item in &layout.elems {
if item.element.borrow().repeated.is_some() {
push_code +=
&format!("self->repeater_{}.ensure_updated(self);", item.element.borrow().id);
push_code += &format!(
"self->repeater_{}.ensure_updated(self);",
ident(&item.element.borrow().id)
);
if repeated_indices.is_some() {
push_code += &format!("repeater_indices[{}] = cells.size();", repeater_idx * 2);
push_code += &format!(
"repeater_indices[{c}] = self->repeater_{id}.inner ? self->repeater_{id}.inner->data.size() : 0;",
c = repeater_idx * 2 + 1,
id = item.element.borrow().id
id = ident(&item.element.borrow().id)
);
}
repeater_idx += 1;
@ -1998,7 +2015,7 @@ fn box_layout_data(
"if (self->repeater_{id}.inner) \
for (auto &&sub_comp : self->repeater_{id}.inner->data) \
cells.push_back((*sub_comp.ptr)->box_layout_data({o}));",
id = item.element.borrow().id,
id = ident(&item.element.borrow().id),
o = to_cpp_orientation(orientation),
);
} else {
@ -2056,7 +2073,7 @@ fn get_layout_info(
"{vt}->layouting_info({{{vt}, const_cast<sixtyfps::cbindgen_private::{ty}*>(&self->{id})}}, {o}, &self->m_window.window_handle())",
vt = elem.borrow().base_type.as_native().cpp_vtable_getter,
ty = elem.borrow().base_type.as_native().class_name,
id = elem.borrow().id,
id = ident(&elem.borrow().id),
o = to_cpp_orientation(orientation),
)
};

View file

@ -27,6 +27,14 @@ use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use std::{collections::BTreeMap, rc::Rc};
fn ident(ident: &str) -> proc_macro2::Ident {
if ident.contains('-') {
format_ident!("r#{}", ident.replace('-', "_"))
} else {
format_ident!("r#{}", ident)
}
}
impl quote::ToTokens for Orientation {
fn to_tokens(&self, tokens: &mut TokenStream) {
let tks = match self {
@ -61,7 +69,7 @@ fn rust_type(ty: &Type) -> Option<proc_macro2::TokenStream> {
Some(quote!(sixtyfps::re_exports::ModelHandle<#inner>))
}
Type::Enumeration(e) => {
let e = format_ident!("r#{}", e.name);
let e = ident(&e.name);
Some(quote!(sixtyfps::re_exports::#e))
}
Type::Brush => Some(quote!(sixtyfps::Brush)),
@ -98,7 +106,7 @@ pub fn generate(doc: &Document, diag: &mut BuildDiagnostics) -> Option<TokenStre
.iter()
.filter_map(|ty| {
if let Type::Struct { fields, name: Some(name), node: Some(_) } = ty {
Some((format_ident!("r#{}", name), generate_struct(name, fields, diag)))
Some((ident(name), generate_struct(name, fields, diag)))
} else {
None
}
@ -147,10 +155,7 @@ fn generate_struct(
let (declared_property_vars, declared_property_types): (Vec<_>, Vec<_>) = fields
.iter()
.map(|(name, ty)| {
(
format_ident!("r#{}", name),
get_rust_type(ty, &crate::diagnostics::SourceLocation::default(), diag),
)
(ident(name), get_rust_type(ty, &crate::diagnostics::SourceLocation::default(), diag))
})
.unzip();
@ -309,7 +314,7 @@ fn generate_component(
let mut declared_callbacks_ret = vec![];
let mut property_and_callback_accessors: Vec<TokenStream> = vec![];
for (prop_name, property_decl) in component.root_element.borrow().property_declarations.iter() {
let prop_ident = format_ident!("r#{}", prop_name);
let prop_ident = ident(prop_name);
let prop = if let Some(alias) = &property_decl.is_alias {
access_named_reference(alias, component, quote!(_self))
} else {
@ -330,7 +335,7 @@ fn generate_component(
let args_name = (0..callback_args.len())
.map(|i| format_ident!("arg_{}", i))
.collect::<Vec<_>>();
let caller_ident = format_ident!("invoke_{}", prop_name);
let caller_ident = format_ident!("invoke_{}", prop_ident);
property_and_callback_accessors.push(quote!(
#[allow(dead_code)]
pub fn #caller_ident(&self, #(#args_name : #callback_args,)*) -> #return_type {
@ -339,7 +344,7 @@ fn generate_component(
}
));
let on_ident = format_ident!("on_{}", prop_name);
let on_ident = format_ident!("on_{}", prop_ident);
let args_index =
(0..callback_args.len()).map(proc_macro2::Literal::usize_unsuffixed);
property_and_callback_accessors.push(
@ -366,8 +371,8 @@ fn generate_component(
let rust_property_type =
get_rust_type(&property_decl.property_type, &property_decl.type_node(), diag);
if property_decl.expose_in_public_api {
let getter_ident = format_ident!("get_{}", prop_name);
let setter_ident = format_ident!("set_{}", prop_name);
let getter_ident = format_ident!("get_{}", prop_ident);
let setter_ident = format_ident!("set_{}", prop_ident);
property_and_callback_accessors.push(quote!(
#[allow(dead_code)]
@ -435,7 +440,7 @@ fn generate_component(
} else if let Some(repeated) = &item.repeated {
let base_component = item.base_type.as_component();
let repeater_index = repeated_element_names.len();
let repeater_id = format_ident!("repeater_{}", item.id);
let repeater_id = format_ident!("repeater_{}", ident(&item.id));
let rep_inner_component_id = self::inner_component_id(&*base_component);
extra_components.push(generate_component(&*base_component, diag).unwrap_or_else(
@ -593,10 +598,8 @@ fn generate_component(
repeated_element_names.push(repeater_id);
repeated_element_components.push(rep_inner_component_id);
} else if item.is_flickable_viewport {
let field_name = format_ident!(
"r#{}",
crate::object_tree::find_parent_element(item_rc).unwrap().borrow().id
);
let field_name =
ident(&crate::object_tree::find_parent_element(item_rc).unwrap().borrow().id);
let children_count = item.children.len() as u32;
let field = access_component_field_offset(&inner_component_id, &field_name);
@ -609,7 +612,7 @@ fn generate_component(
}
));
} else {
let field_name = format_ident!("r#{}", item.id);
let field_name = ident(&item.id);
let children_count = item.children.len() as u32;
let field = access_component_field_offset(&inner_component_id, &field_name);
@ -622,7 +625,7 @@ fn generate_component(
}
));
item_names.push(field_name);
item_types.push(format_ident!("r#{}", item.base_type.as_native().class_name));
item_types.push(ident(&item.base_type.as_native().class_name));
}
});
@ -955,16 +958,16 @@ fn inner_component_id(component: &Component) -> proc_macro2::Ident {
/// Return an identifier suitable for this component for the developer facing API
fn public_component_id(component: &Component) -> proc_macro2::Ident {
if component.is_global() {
format_ident!("r#{}", component.root_element.borrow().id)
ident(&component.root_element.borrow().id)
} else if component.id.is_empty() {
let s = &component.root_element.borrow().id;
// Capitalize first letter:
let mut it = s.chars();
let id =
it.next().map(|c| c.to_ascii_uppercase()).into_iter().chain(it).collect::<String>();
format_ident!("r#{}", id)
ident(&id)
} else {
format_ident!("r#{}", component.id)
ident(&component.id)
}
}
@ -974,7 +977,7 @@ fn property_animation_tokens(
) -> Option<TokenStream> {
let animation = animation.borrow();
let bindings = animation.bindings.iter().map(|(prop, initializer)| {
let prop_ident = format_ident!("r#{}", prop);
let prop_ident = ident(prop);
let initializer = compile_expression(initializer, component);
quote!(#prop_ident: #initializer as _)
});
@ -1019,15 +1022,13 @@ fn access_member(
let enclosing_component = e.enclosing_component.upgrade().unwrap();
if Rc::ptr_eq(component, &enclosing_component) {
let inner_component_id = inner_component_id(&enclosing_component);
let name_ident = format_ident!("r#{}", name);
let name_ident = ident(name);
if e.property_declarations.contains_key(name) || is_special || component.is_global() {
let field = access_component_field_offset(&inner_component_id, &name_ident);
quote!(#field.apply_pin(#component_rust))
} else if e.is_flickable_viewport {
let elem_ident = format_ident!(
"r#{}",
crate::object_tree::find_parent_element(element).unwrap().borrow().id
);
let elem_ident =
ident(&crate::object_tree::find_parent_element(element).unwrap().borrow().id);
let element_field = access_component_field_offset(&inner_component_id, &elem_ident);
quote!((#element_field
@ -1036,8 +1037,8 @@ fn access_member(
.apply_pin(#component_rust)
)
} else {
let elem_ident = format_ident!("r#{}", e.id);
let elem_ty = format_ident!("r#{}", e.base_type.as_native().class_name);
let elem_ident = ident(&e.id);
let elem_ty = ident(&e.base_type.as_native().class_name);
let element_field = access_component_field_offset(&inner_component_id, &elem_ident);
quote!((#element_field + #elem_ty::FIELD_OFFSETS.#name_ident)
@ -1110,7 +1111,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
(Type::Struct { ref fields, .. }, Type::Component(c)) => {
let fields = fields.iter().enumerate().map(|(index, (name, _))| {
let index = proc_macro2::Literal::usize_unsuffixed(index);
let name = format_ident!("r#{}", name);
let name = ident(name);
quote!(#name: obj.#index as _)
});
let id : TokenStream = c.id.parse().unwrap();
@ -1119,7 +1120,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
(Type::Struct { ref fields, .. }, Type::Struct{ name: Some(n), .. }) => {
let fields = fields.iter().enumerate().map(|(index, (name, _))| {
let index = proc_macro2::Literal::usize_unsuffixed(index);
let name = format_ident!("r#{}", name);
let name = ident(name);
quote!(#name: obj.#index as _)
});
let id = struct_name_to_tokens(n);
@ -1222,7 +1223,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
quote!((#base_e).#index )
}
Type::Struct { .. } => {
let name = format_ident!("r#{}", name);
let name = ident(name);
let base_e = compile_expression(base, component);
quote!((#base_e).#name)
}
@ -1284,7 +1285,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
if let Expression::ElementReference(item) = &arguments[0] {
let item = item.upgrade().unwrap();
let item = item.borrow();
let item_id = format_ident!("r#{}", item.id);
let item_id = ident(&item.id);
let item_field = access_component_field_offset(&format_ident!("Self"), &item_id);
quote!(
#item_field.apply_pin(_self).layouting_info(#orient, &_self.window.window_handle())
@ -1450,7 +1451,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
});
if let Some(name) = name {
let name : TokenStream = struct_name_to_tokens(name.as_str());
let keys = fields.keys().map(|k| k.parse::<TokenStream>().unwrap());
let keys = fields.keys().map(|k| ident(&k));
quote!(#name { #(#keys: #elem,)* })
} else {
// This will produce a tuple
@ -1463,11 +1464,11 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
Expression::PathElements { elements } => compile_path(elements, component),
Expression::StoreLocalVariable { name, value } => {
let value = compile_expression(value, component);
let name = format_ident!("r#{}", name);
let name = ident(name);
quote!(let #name = #value;)
}
Expression::ReadLocalVariable { name, .. } => {
let name = format_ident!("r#{}", name);
let name = ident(name);
quote!(#name)
}
Expression::EasingCurve(EasingCurve::Linear) => {
@ -1488,8 +1489,8 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
))
}
Expression::EnumerationValue(value) => {
let base_ident = format_ident!("r#{}", value.enumeration.name);
let value_ident = format_ident!("r#{}", value.to_string());
let base_ident = ident(&value.enumeration.name);
let value_ident = ident(&value.to_string());
quote!(sixtyfps::re_exports::#base_ident::#value_ident)
}
Expression::ReturnStatement(expr) => {
@ -1590,7 +1591,7 @@ fn compile_expression(expr: &Expression, component: &Rc<Component>) -> TokenStre
/// Return a TokenStream for a name (as in [`Type::Struct::name`])
fn struct_name_to_tokens(name: &str) -> TokenStream {
// the name match the C++ signature so we need to change that to the rust namespace
let mut name = name.replace("::private_api::", "::re_exports::");
let mut name = name.replace("::private_api::", "::re_exports::").replace('-', "_");
if !name.contains("::") {
name.insert_str(0, "r#")
}
@ -1631,7 +1632,7 @@ fn compile_assignment(
(quote!(#index), fields[name].clone())
}
Type::Struct { fields, name: Some(_), .. } => {
let n = format_ident!("r#{}", name);
let n = ident(name);
(quote!(#n), fields[name].clone())
}
_ => panic!("Expression::ObjectAccess's base expression is not an Object type"),
@ -1762,7 +1763,7 @@ fn box_layout_data(
let mut repeater_idx = 0usize;
for item in &layout.elems {
if item.element.borrow().repeated.is_some() {
let repeater_id = format_ident!("repeater_{}", item.element.borrow().id);
let repeater_id = format_ident!("repeater_{}", ident(&item.element.borrow().id));
let rep_inner_component_id =
self::inner_component_id(item.element.borrow().base_type.as_component());
repeated_count = quote!(#repeated_count + _self.#repeater_id.len());
@ -1869,7 +1870,7 @@ fn get_layout_info(
let li = access_named_reference(layout_info_prop, component, quote!(_self));
quote! {#li.get()}
} else {
let elem_id = format_ident!("r#{}", elem.borrow().id);
let elem_id = ident(&elem.borrow().id);
let inner_component_id = inner_component_id(component);
quote!(#inner_component_id::FIELD_OFFSETS.#elem_id.apply_pin(_self).layouting_info(#orientation, &_self.window.window_handle()))
};
@ -1877,9 +1878,7 @@ fn get_layout_info(
if constraints.has_explicit_restrictions() {
let (name, expr): (Vec<_>, Vec<_>) = constraints
.for_each_restrictions(orientation)
.map(|(e, s)| {
(format_ident!("r#{}", s), access_named_reference(e, component, quote!(_self)))
})
.map(|(e, s)| (ident(s), access_named_reference(e, component, quote!(_self))))
.unzip();
quote!({
let mut layout_info = #layout_info;
@ -1954,7 +1953,7 @@ fn compile_path(path: &Path, component: &Rc<Component>) -> TokenStream {
.bindings
.iter()
.map(|(property, expr)| {
let prop_ident = format_ident!("r#{}", property);
let prop_ident = ident(property);
let binding_expr = compile_expression(expr, component);
quote!(#prop_ident: #binding_expr as _).to_string()

View file

@ -163,7 +163,7 @@ impl Display for Type {
Type::String => write!(f, "string"),
Type::Duration => write!(f, "duration"),
Type::Angle => write!(f, "angle"),
Type::PhysicalLength => write!(f, "physical_length"),
Type::PhysicalLength => write!(f, "physical-length"),
Type::LogicalLength => write!(f, "length"),
Type::Percent => write!(f, "percent"),
Type::Color => write!(f, "color"),

View file

@ -143,14 +143,14 @@ pub struct LayoutConstraints {
impl LayoutConstraints {
pub fn new(element: &ElementRc, diag: &mut BuildDiagnostics) -> Self {
let mut constraints = Self {
min_width: binding_reference(element, "min_width"),
max_width: binding_reference(element, "max_width"),
min_height: binding_reference(element, "min_height"),
max_height: binding_reference(element, "max_height"),
preferred_width: binding_reference(element, "preferred_width"),
preferred_height: binding_reference(element, "preferred_height"),
horizontal_stretch: binding_reference(element, "horizontal_stretch"),
vertical_stretch: binding_reference(element, "vertical_stretch"),
min_width: binding_reference(element, "min-width"),
max_width: binding_reference(element, "max-width"),
min_height: binding_reference(element, "min-height"),
max_height: binding_reference(element, "max-height"),
preferred_width: binding_reference(element, "preferred-width"),
preferred_height: binding_reference(element, "preferred-height"),
horizontal_stretch: binding_reference(element, "horizontal-stretch"),
vertical_stretch: binding_reference(element, "vertical-stretch"),
fixed_width: false,
fixed_height: false,
};
@ -368,16 +368,16 @@ impl LayoutGeometry {
let alignment = binding_reference(layout_element, "alignment");
let padding = || binding_reference(layout_element, "padding");
init_fake_property(layout_element, "padding_left", padding);
init_fake_property(layout_element, "padding_right", padding);
init_fake_property(layout_element, "padding_top", padding);
init_fake_property(layout_element, "padding_bottom", padding);
init_fake_property(layout_element, "padding-left", padding);
init_fake_property(layout_element, "padding-right", padding);
init_fake_property(layout_element, "padding-top", padding);
init_fake_property(layout_element, "padding-bottom", padding);
let padding = Padding {
left: binding_reference(layout_element, "padding_left").or_else(padding),
right: binding_reference(layout_element, "padding_right").or_else(padding),
top: binding_reference(layout_element, "padding_top").or_else(padding),
bottom: binding_reference(layout_element, "padding_bottom").or_else(padding),
left: binding_reference(layout_element, "padding-left").or_else(padding),
right: binding_reference(layout_element, "padding-right").or_else(padding),
top: binding_reference(layout_element, "padding-top").or_else(padding),
bottom: binding_reference(layout_element, "padding-bottom").or_else(padding),
};
let rect = LayoutRect::install_on_element(layout_element);

View file

@ -132,7 +132,7 @@ pub fn load_builtins(register: &mut TypeRegister) {
n.rust_type_constructor = parse_annotation("rust_type_constructor", &e).map(|x| x.unwrap());
let global = if let Some(base) = e.QualifiedName() {
let base = QualifiedTypeName::from_node(base).to_string();
if base != "_" {
if base != "-" {
n.parent = Some(natives.get(&base).unwrap().native_class.clone())
};
false

View file

@ -409,14 +409,14 @@ impl LookupObject for EasingSpecific {
use EasingCurve::CubicBezier;
None.or_else(|| f("linear", Expression::EasingCurve(EasingCurve::Linear)))
.or_else(|| f("ease", Expression::EasingCurve(CubicBezier(0.25, 0.1, 0.25, 1.0))))
.or_else(|| f("ease_in", Expression::EasingCurve(CubicBezier(0.42, 0.0, 1.0, 1.0))))
.or_else(|| f("ease-in", Expression::EasingCurve(CubicBezier(0.42, 0.0, 1.0, 1.0))))
.or_else(|| {
f("ease_in_out", Expression::EasingCurve(CubicBezier(0.42, 0.0, 0.58, 1.0)))
f("ease-in-out", Expression::EasingCurve(CubicBezier(0.42, 0.0, 0.58, 1.0)))
})
.or_else(|| f("ease_out", Expression::EasingCurve(CubicBezier(0.0, 0.0, 0.58, 1.0))))
.or_else(|| f("ease-out", Expression::EasingCurve(CubicBezier(0.0, 0.0, 0.58, 1.0))))
.or_else(|| {
f(
"cubic_bezier",
"cubic-bezier",
Expression::BuiltinMacroReference(
BuiltinMacroFunction::CubicBezier,
ctx.current_token.clone(),
@ -568,8 +568,8 @@ impl<'a> LookupObject for StringExpression<'a> {
ctx.current_token.as_ref().map(|t| t.to_source_location()),
)),
};
None.or_else(|| f("is_float", member_function(BuiltinFunction::StringIsFloat)))
.or_else(|| f("to_float", member_function(BuiltinFunction::StringToFloat)))
None.or_else(|| f("is-float", member_function(BuiltinFunction::StringIsFloat)))
.or_else(|| f("to-float", member_function(BuiltinFunction::StringToFloat)))
}
}
struct ColorExpression<'a>(&'a Expression);

View file

@ -305,7 +305,7 @@ impl TransitionPropertyAnimation {
Expression::BinaryExpression {
lhs: Box::new(Expression::StructFieldAccess {
base: Box::new(state),
name: (if self.is_out { "previous_state" } else { "current_state" }).into(),
name: (if self.is_out { "previous-state" } else { "current-state" }).into(),
}),
rhs: Box::new(Expression::NumberLiteral(self.state_id as _, Unit::None)),
op: '=',
@ -972,11 +972,11 @@ impl Element {
) -> ElementRc {
let is_listview = if parent.borrow().base_type.to_string() == "ListView" {
Some(ListViewInfo {
viewport_y: NamedReference::new(parent, "viewport_y"),
viewport_height: NamedReference::new(parent, "viewport_height"),
viewport_width: NamedReference::new(parent, "viewport_width"),
listview_height: NamedReference::new(parent, "visible_height"),
listview_width: NamedReference::new(parent, "visible_width"),
viewport_y: NamedReference::new(parent, "viewport-y"),
viewport_height: NamedReference::new(parent, "viewport-height"),
viewport_width: NamedReference::new(parent, "viewport-width"),
listview_height: NamedReference::new(parent, "visible-height"),
listview_width: NamedReference::new(parent, "visible-width"),
})
} else {
None

View file

@ -846,7 +846,7 @@ pub fn identifier_text(node: &SyntaxNode) -> Option<String> {
}
pub fn normalize_identifier(ident: &str) -> String {
ident.replace('-', "_")
ident.replace('_', "-")
}
// Actual parser

View file

@ -37,10 +37,10 @@ pub async fn apply_default_properties_from_style(
let mut elem = elem.borrow_mut();
match elem.base_type.to_string().as_str() {
"TextInput" => {
elem.bindings.set_binding_if_not_set("text_cursor_width".into(), || {
elem.bindings.set_binding_if_not_set("text-cursor-width".into(), || {
Expression::PropertyReference(NamedReference::new(
&style_metrics.root_element,
"text_cursor_width",
"text-cursor-width",
))
.into()
});
@ -49,7 +49,7 @@ pub async fn apply_default_properties_from_style(
elem.bindings.set_binding_if_not_set("background".into(), || {
Expression::PropertyReference(NamedReference::new(
&style_metrics.root_element,
"window_background",
"window-background",
))
.into()
});

View file

@ -210,10 +210,10 @@ fn visit_implicit_layout_info_dependencies(
}
"Text" => {
vis(&NamedReference::new(item, "text"));
vis(&NamedReference::new(item, "font_family"));
vis(&NamedReference::new(item, "font_size"));
vis(&NamedReference::new(item, "font_weight"));
vis(&NamedReference::new(item, "letter_spacing"));
vis(&NamedReference::new(item, "font-family"));
vis(&NamedReference::new(item, "font-size"));
vis(&NamedReference::new(item, "font-weight"));
vis(&NamedReference::new(item, "letter-spacing"));
vis(&NamedReference::new(item, "wrap"));
vis(&NamedReference::new(item, "overflow"));
if orientation == Orientation::Vertical {

View file

@ -60,7 +60,7 @@ pub fn handle_clip(
fn create_clip_element(parent_elem: &ElementRc, native_clip: &Rc<NativeClass>) {
let mut parent = parent_elem.borrow_mut();
let clip = Rc::new(RefCell::new(Element {
id: format!("{}_clip", parent.id),
id: format!("{}-clip", parent.id),
base_type: Type::Native(native_clip.clone()),
children: std::mem::take(&mut parent.children),
enclosing_component: parent.enclosing_component.clone(),
@ -78,7 +78,7 @@ fn create_clip_element(parent_elem: &ElementRc, native_clip: &Rc<NativeClass>) {
)
})
.collect();
for optional_binding in ["border_radius", "border_width"].iter() {
for optional_binding in ["border-radius", "border-width"].iter() {
if parent_elem.borrow().bindings.contains_key(*optional_binding) {
clip.borrow_mut().bindings.insert(
optional_binding.to_string(),

View file

@ -90,7 +90,7 @@ pub fn default_geometry(root_component: &Rc<Component>, diag: &mut BuildDiagnost
let PropertyLookupResult {
resolved_name: image_fit_prop_name,
property_type: image_fit_prop_type,
} = elem.borrow().lookup_property("image_fit");
} = elem.borrow().lookup_property("image-fit");
elem.borrow_mut().bindings.set_binding_if_not_set(
image_fit_prop_name.into(),
@ -137,12 +137,12 @@ fn gen_layout_info_prop(elem: &ElementRc) {
let li_v = super::lower_layout::create_new_prop(
elem,
"layoutinfo_v",
"layoutinfo-v",
crate::layout::layout_info_type(),
);
let li_h = super::lower_layout::create_new_prop(
elem,
"layoutinfo_h",
"layoutinfo-h",
crate::layout::layout_info_type(),
);
elem.borrow_mut().layout_info_prop = Some((li_h.clone(), li_v.clone()));

View file

@ -51,7 +51,7 @@ fn create_viewport_element(flickable_elem: &ElementRc, native_rect: &Rc<NativeCl
let mut flickable = flickable_elem.borrow_mut();
let flickable = &mut *flickable;
let viewport = Rc::new(RefCell::new(Element {
id: format!("{}_viewport", flickable.id),
id: format!("{}-viewport", flickable.id),
base_type: Type::Native(native_rect.clone()),
children: std::mem::take(&mut flickable.children),
enclosing_component: flickable.enclosing_component.clone(),
@ -59,7 +59,7 @@ fn create_viewport_element(flickable_elem: &ElementRc, native_rect: &Rc<NativeCl
..Element::default()
}));
for (prop, info) in &flickable.base_type.as_builtin().properties {
if let Some(vp_prop) = prop.strip_prefix("viewport_") {
if let Some(vp_prop) = prop.strip_prefix("viewport-") {
let nr = NamedReference::new(&viewport, vp_prop);
flickable.property_declarations.insert(prop.to_owned(), info.ty.clone().into());
match flickable.bindings.entry(prop.to_owned()) {
@ -93,35 +93,35 @@ fn fixup_geometry(flickable_elem: &ElementRc) {
};
if !flickable_elem.borrow().bindings.contains_key("height") {
forward_minmax_of("max_height", '<');
forward_minmax_of("preferred_height", '<');
forward_minmax_of("max-height", '<');
forward_minmax_of("preferred-height", '<');
}
if !flickable_elem.borrow().bindings.contains_key("width") {
forward_minmax_of("max_width", '<');
forward_minmax_of("preferred_width", '<');
forward_minmax_of("max-width", '<');
forward_minmax_of("preferred-width", '<');
}
set_binding_if_not_explicit(flickable_elem, "viewport_width", || {
set_binding_if_not_explicit(flickable_elem, "viewport-width", || {
Some(
flickable_elem
.borrow()
.children
.iter()
.filter(|x| is_layout(&x.borrow().base_type))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min_width")))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min-width")))
.fold(
Expression::PropertyReference(NamedReference::new(flickable_elem, "width")),
|lhs, rhs| crate::builtin_macros::min_max_expression(lhs, rhs, '>'),
),
)
});
set_binding_if_not_explicit(flickable_elem, "viewport_height", || {
set_binding_if_not_explicit(flickable_elem, "viewport-height", || {
Some(
flickable_elem
.borrow()
.children
.iter()
.filter(|x| is_layout(&x.borrow().base_type))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min_height")))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min-height")))
.fold(
Expression::PropertyReference(NamedReference::new(flickable_elem, "height")),
|lhs, rhs| crate::builtin_macros::min_max_expression(lhs, rhs, '>'),

View file

@ -24,14 +24,14 @@ enum FocusCheckResult {
}
fn element_focus_check(element: &ElementRc) -> FocusCheckResult {
if let Some(forwarded_focus_binding) = element.borrow().bindings.get("forward_focus") {
if let Some(forwarded_focus_binding) = element.borrow().bindings.get("forward-focus") {
if let Expression::ElementReference(target) = &forwarded_focus_binding.expression {
return FocusCheckResult::FocusForwarded(
target.upgrade().unwrap(),
forwarded_focus_binding.to_source_location(),
);
} else {
panic!("internal error: forward_focus property is of type ElementReference but received non-element-reference binding");
panic!("internal error: forward-focus property is of type ElementReference but received non-element-reference binding");
}
}
@ -117,10 +117,10 @@ pub fn determine_initial_focus_item(component: &Rc<Component>, diag: &mut BuildD
}
}
/// The `forward_focus` property is not a real property that can be generated, so remove any bindings to it
/// The `forward-focus` property is not a real property that can be generated, so remove any bindings to it
/// to avoid them being materialized.
pub fn erase_forward_focus_properties(component: &Rc<Component>) {
recurse_elem_no_borrow(&component.root_element, &(), &mut |elem, _| {
elem.borrow_mut().bindings.remove("forward_focus");
elem.borrow_mut().bindings.remove("forward-focus");
})
}

View file

@ -84,13 +84,13 @@ fn lower_grid_layout(
};
let layout_cache_prop_h =
create_new_prop(grid_layout_element, "layout_cache_h", Type::LayoutCache);
create_new_prop(grid_layout_element, "layout-cache-h", Type::LayoutCache);
let layout_cache_prop_v =
create_new_prop(grid_layout_element, "layout_cache_v", Type::LayoutCache);
create_new_prop(grid_layout_element, "layout-cache-v", Type::LayoutCache);
let layout_info_prop_h =
create_new_prop(grid_layout_element, "layoutinfo_h", layout_info_type());
create_new_prop(grid_layout_element, "layoutinfo-h", layout_info_type());
let layout_info_prop_v =
create_new_prop(grid_layout_element, "layoutinfo_v", layout_info_type());
create_new_prop(grid_layout_element, "layoutinfo-v", layout_info_type());
let mut row = 0;
let mut col = 0;
@ -244,9 +244,9 @@ fn lower_box_layout(
geometry: LayoutGeometry::new(layout_element),
};
let layout_cache_prop = create_new_prop(layout_element, "layout_cache", Type::LayoutCache);
let layout_info_prop_v = create_new_prop(layout_element, "layoutinfo_v", layout_info_type());
let layout_info_prop_h = create_new_prop(layout_element, "layoutinfo_h", layout_info_type());
let layout_cache_prop = create_new_prop(layout_element, "layout-cache", Type::LayoutCache);
let layout_info_prop_v = create_new_prop(layout_element, "layoutinfo-v", layout_info_type());
let layout_info_prop_h = create_new_prop(layout_element, "layoutinfo-h", layout_info_type());
let layout_children = std::mem::take(&mut layout_element.borrow_mut().children);
@ -342,7 +342,7 @@ fn lower_path_layout(
layout_element: &ElementRc,
diag: &mut BuildDiagnostics,
) {
let layout_cache_prop = create_new_prop(layout_element, "layout_cache", Type::LayoutCache);
let layout_cache_prop = create_new_prop(layout_element, "layout-cache", Type::LayoutCache);
let path_elements_expr = match layout_element.borrow_mut().bindings.remove("elements") {
Some(BindingExpression { expression: Expression::PathElements { elements }, .. }) => {
@ -426,14 +426,14 @@ fn create_layout_item(
}
let mut item = item.borrow_mut();
let b = item.bindings.remove(prop).unwrap();
item.bindings.insert(format!("min_{}", prop), b.clone());
item.bindings.insert(format!("max_{}", prop), b);
item.bindings.insert(format!("min-{}", prop), b.clone());
item.bindings.insert(format!("max-{}", prop), b);
item.property_declarations.insert(
format!("min_{}", prop),
format!("min-{}", prop),
PropertyDeclaration { property_type: Type::Percent, ..PropertyDeclaration::default() },
);
item.property_declarations.insert(
format!("max_{}", prop),
format!("max-{}", prop),
PropertyDeclaration { property_type: Type::Percent, ..PropertyDeclaration::default() },
);
};

View file

@ -123,7 +123,7 @@ fn create_coordinate(
};
}
let parent_element = parent_stack.last().unwrap();
let property_name = format!("{}_popup_{}", popup_comp.root_element.borrow().id, coord);
let property_name = format!("{}-popup-{}", popup_comp.root_element.borrow().id, coord);
parent_element
.borrow_mut()
.property_declarations

View file

@ -43,23 +43,23 @@ fn create_box_shadow_element(
}
let mut element = Element {
id: format!("{}_shadow", sibling_element.borrow().id),
id: format!("{}-shadow", sibling_element.borrow().id),
base_type: type_register.lookup_element("BoxShadow").unwrap(),
enclosing_component: sibling_element.borrow().enclosing_component.clone(),
bindings: shadow_property_bindings
.into_iter()
.map(|(shadow_prop_name, expr)| {
(shadow_prop_name.strip_prefix("drop_shadow_").unwrap().to_string(), expr)
(shadow_prop_name.strip_prefix("drop-shadow-").unwrap().to_string(), expr)
})
.collect(),
..Default::default()
};
// FIXME: remove the border_radius manual mapping.
if sibling_element.borrow().bindings.contains_key("border_radius") {
// FIXME: remove the border-radius manual mapping.
if sibling_element.borrow().bindings.contains_key("border-radius") {
element.bindings.insert(
"border_radius".to_string(),
Expression::PropertyReference(NamedReference::new(sibling_element, "border_radius"))
"border-radius".to_string(),
Expression::PropertyReference(NamedReference::new(sibling_element, "border-radius"))
.into(),
);
}

View file

@ -44,7 +44,7 @@ fn lower_state_in_element(
let state_property_ref = if has_transitions {
Expression::StructFieldAccess {
base: Box::new(state_property.clone()),
name: "current_state".into(),
name: "current-state".into(),
}
} else {
state_property.clone()
@ -172,7 +172,7 @@ fn compute_state_property_name(root_element: &ElementRc) -> String {
while root_element.borrow().lookup_property(property_name.as_ref()).property_type
!= Type::Invalid
{
property_name += "_";
property_name += "-";
}
property_name
}

View file

@ -88,7 +88,7 @@ fn process_tabwidget(
set_geometry_prop(elem, child, "width", diag);
set_geometry_prop(elem, child, "height", diag);
let condition = Expression::BinaryExpression {
lhs: Expression::PropertyReference(NamedReference::new(elem, "current_index")).into(),
lhs: Expression::PropertyReference(NamedReference::new(elem, "current-index")).into(),
rhs: Expression::NumberLiteral(index as _, Unit::None).into(),
op: '=',
};
@ -101,7 +101,7 @@ fn process_tabwidget(
}
let mut tab = Element {
id: format!("{}_tab{}", elem.borrow().id, index),
id: format!("{}-tab{}", elem.borrow().id, index),
base_type: tab_impl.clone(),
enclosing_component: elem.borrow().enclosing_component.clone(),
..Default::default()
@ -112,21 +112,21 @@ fn process_tabwidget(
);
tab.bindings.insert(
"current".to_owned(),
Expression::TwoWayBinding(NamedReference::new(elem, "current_index"), None).into(),
Expression::TwoWayBinding(NamedReference::new(elem, "current-index"), None).into(),
);
tab.bindings.insert(
"tab_index".to_owned(),
"tab-index".to_owned(),
Expression::NumberLiteral(index as _, Unit::None).into(),
);
tab.bindings.insert(
"num_tabs".to_owned(),
"num-tabs".to_owned(),
Expression::NumberLiteral(num_tabs as _, Unit::None).into(),
);
tabs.push(Rc::new(RefCell::new(tab)));
}
let tabbar = Element {
id: format!("{}_tabbar", elem.borrow().id),
id: format!("{}-tabbar", elem.borrow().id),
base_type: tabbar_impl.clone(),
enclosing_component: elem.borrow().enclosing_component.clone(),
children: tabs,
@ -138,27 +138,27 @@ fn process_tabwidget(
set_tabbar_geometry_prop(elem, &tabbar, "width");
set_tabbar_geometry_prop(elem, &tabbar, "height");
elem.borrow_mut().bindings.insert(
"tabbar_preferred_width".to_owned(),
Expression::TwoWayBinding(NamedReference::new(&tabbar, "preferred_width"), None).into(),
"tabbar-preferred-width".to_owned(),
Expression::TwoWayBinding(NamedReference::new(&tabbar, "preferred-width"), None).into(),
);
elem.borrow_mut().bindings.insert(
"tabbar_preferred_height".to_owned(),
Expression::TwoWayBinding(NamedReference::new(&tabbar, "preferred_height"), None).into(),
"tabbar-preferred-height".to_owned(),
Expression::TwoWayBinding(NamedReference::new(&tabbar, "preferred-height"), None).into(),
);
if let Some(expr) = children
.iter()
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min_width")))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min-width")))
.fold1(|lhs, rhs| crate::builtin_macros::min_max_expression(lhs, rhs, '>'))
{
elem.borrow_mut().bindings.insert("content_min_width".into(), expr.into());
elem.borrow_mut().bindings.insert("content-min-width".into(), expr.into());
};
if let Some(expr) = children
.iter()
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min_height")))
.map(|x| Expression::PropertyReference(NamedReference::new(x, "min-height")))
.fold1(|lhs, rhs| crate::builtin_macros::min_max_expression(lhs, rhs, '>'))
{
elem.borrow_mut().bindings.insert("content_min_height".into(), expr.into());
elem.borrow_mut().bindings.insert("content-min-height".into(), expr.into());
};
children.push(tabbar);
@ -175,7 +175,7 @@ fn set_geometry_prop(
prop.into(),
Expression::PropertyReference(NamedReference::new(
tab_widget,
&format!("content_{}", prop),
&format!("content-{}", prop),
))
.into(),
);
@ -190,7 +190,7 @@ fn set_geometry_prop(
fn set_tabbar_geometry_prop(tab_widget: &ElementRc, tabbar: &ElementRc, prop: &str) {
tabbar.borrow_mut().bindings.insert(
prop.into(),
Expression::PropertyReference(NamedReference::new(tab_widget, &format!("tabbar_{}", prop)))
Expression::PropertyReference(NamedReference::new(tab_widget, &format!("tabbar-{}", prop)))
.into(),
);
}

View file

@ -132,14 +132,14 @@ fn has_declared_property(elem: &Element, prop: &str) -> bool {
/// Initialize a sensible default binding for the now materialized property
fn initialize(elem: &ElementRc, name: &str) -> Option<Expression> {
let expr = match name {
"min_height" => layout_constraint_prop(elem, "min", Orientation::Vertical),
"min_width" => layout_constraint_prop(elem, "min", Orientation::Horizontal),
"max_height" => layout_constraint_prop(elem, "max", Orientation::Vertical),
"max_width" => layout_constraint_prop(elem, "max", Orientation::Horizontal),
"preferred_height" => layout_constraint_prop(elem, "preferred", Orientation::Vertical),
"preferred_width" => layout_constraint_prop(elem, "preferred", Orientation::Horizontal),
"horizontal_stretch" => layout_constraint_prop(elem, "stretch", Orientation::Horizontal),
"vertical_stretch" => layout_constraint_prop(elem, "stretch", Orientation::Vertical),
"min-height" => layout_constraint_prop(elem, "min", Orientation::Vertical),
"min-width" => layout_constraint_prop(elem, "min", Orientation::Horizontal),
"max-height" => layout_constraint_prop(elem, "max", Orientation::Vertical),
"max-width" => layout_constraint_prop(elem, "max", Orientation::Horizontal),
"preferred-height" => layout_constraint_prop(elem, "preferred", Orientation::Vertical),
"preferred-width" => layout_constraint_prop(elem, "preferred", Orientation::Horizontal),
"horizontal-stretch" => layout_constraint_prop(elem, "stretch", Orientation::Horizontal),
"vertical-stretch" => layout_constraint_prop(elem, "stretch", Orientation::Vertical),
"opacity" => Expression::NumberLiteral(1., Unit::None),
"visible" => Expression::BoolLiteral(true),
_ => return None,

View file

@ -124,7 +124,7 @@ fn fixup_reference(nr: &mut NamedReference) {
}
fn map_name(e: &ElementRc, s: &str) -> String {
format!("{}_{}", e.borrow().id, s)
format!("{}-{}", e.borrow().id, s)
}
/// Optimized item are not used for the fact that they are items, but their properties

View file

@ -57,7 +57,7 @@ fn create_repeater_components(component: &Rc<Component>) {
if is_listview && !comp.root_element.borrow().bindings.contains_key("height") {
let preferred = Expression::PropertyReference(NamedReference::new(
&comp.root_element,
"preferred_height",
"preferred-height",
));
comp.root_element.borrow_mut().bindings.insert("height".into(), preferred.into());
}

View file

@ -142,7 +142,7 @@ fn select_minimal_class() {
assert_eq!(
select_minimal_class_based_on_property_usage(
&rect.native_class,
["border_width".to_owned()].iter()
["border-width".to_owned()].iter()
)
.class_name,
"BorderRectangle",
@ -150,7 +150,7 @@ fn select_minimal_class() {
assert_eq!(
select_minimal_class_based_on_property_usage(
&rect.native_class,
["border_width".to_owned(), "x".to_owned()].iter()
["border-width".to_owned(), "x".to_owned()].iter()
)
.class_name,
"BorderRectangle",

View file

@ -502,9 +502,12 @@ impl Expression {
let result = match global_lookup.lookup(ctx, &first_str) {
None => {
if let Some(minus_pos) = first.text().find('-') {
// Attempt to recover if the user wanted to write "-"
// Attempt to recover if the user wanted to write "-" for minus
let first_str = &first.text()[0..minus_pos];
if global_lookup.lookup(ctx, first_str).is_some() {
if global_lookup
.lookup(ctx, &crate::parser::normalize_identifier(first_str))
.is_some()
{
ctx.diag.push_error(format!("Unknown unqualified identifier '{}'. Use space before the '-' if you meant a subtraction", first.text()), &node);
return Expression::Invalid;
}
@ -993,7 +996,10 @@ fn continue_lookup_within_element(
};
if let Some(minus_pos) = second.text().find('-') {
// Attempt to recover if the user wanted to write "-"
if elem.borrow().lookup_property(&second.text()[0..minus_pos]).property_type
if elem
.borrow()
.lookup_property(&crate::parser::normalize_identifier(&second.text()[0..minus_pos]))
.property_type
!= Type::Invalid
{
err(". Use space before the '-' if you meant a subtraction");

View file

@ -75,7 +75,7 @@ pub(crate) fn handle_transform_and_opacity(
fn create_opacity_element(child: &ElementRc, type_register: &TypeRegister) -> ElementRc {
let element = Element {
id: format!("{}_opacity", child.borrow().id),
id: format!("{}-opacity", child.borrow().id),
base_type: type_register.lookup_element("Opacity").unwrap(),
enclosing_component: child.borrow().enclosing_component.clone(),
bindings: std::iter::once((

View file

@ -27,7 +27,7 @@ pub fn assign_unique_id(component: &Rc<Component>) {
} else {
elem_mut.base_type.to_string().to_ascii_lowercase()
};
elem_mut.id = format!("{}_{}", old_id, count);
elem_mut.id = format!("{}-{}", old_id, count);
});
rename_globals(component, count);
@ -42,7 +42,7 @@ fn rename_globals(component: &Rc<Component>, mut count: u32) {
// builtin global keeps its name
root.id = g.id.clone();
} else {
root.id = format!("{}_{}", g.id, count);
root.id = format!("{}-{}", g.id, count);
}
}
}

View file

@ -26,7 +26,7 @@ pub fn handle_visible(component: &Rc<Component>, type_register: &TypeRegister) {
&mut |elem: &ElementRc, _| {
let is_lowered_from_visible_property =
elem.borrow().native_class().map_or(false, |n| {
Rc::ptr_eq(&n, &native_clip) && elem.borrow().id.ends_with("_visibility")
Rc::ptr_eq(&n, &native_clip) && elem.borrow().id.ends_with("-visibility")
});
if is_lowered_from_visible_property {
// This is the element we just created. Skip it.
@ -72,7 +72,7 @@ pub fn handle_visible(component: &Rc<Component>, type_register: &TypeRegister) {
fn create_visibility_element(child: &ElementRc, native_clip: &Rc<NativeClass>) -> ElementRc {
let element = Element {
id: format!("{}_visibility", child.borrow().id),
id: format!("{}-visibility", child.borrow().id),
base_type: Type::Native(native_clip.clone()),
enclosing_component: child.borrow().enclosing_component.clone(),
bindings: std::iter::once((

View file

@ -47,7 +47,7 @@ Test := Rectangle {
WithStates {
extra_background: background;
// ^error{The binding for the property 'extra_background' is part of a binding loop}
// ^error{The binding for the property 'extra-background' is part of a binding loop}
}
}

View file

@ -11,10 +11,10 @@ LICENSE END */
TC := Rectangle {
outer := VerticalLayout {
// ^error{The binding for the property 'width' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo_h' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo-h' is part of a binding loop}
inner := HorizontalLayout {
// ^error{The binding for the property 'width' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo_h' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo-h' is part of a binding loop}
inner_inner := VerticalLayout {
width: parent.width;
// ^error{The binding for the property 'width' is part of a binding loop}
@ -27,8 +27,8 @@ TC := Rectangle {
Test := Rectangle {
VerticalLayout {
// ^error{The binding for the property 'layoutinfo_h' is part of a binding loop} // FIXME: That's an internal property, but people might understand
// ^^error{The binding for the property 'min_width' is part of a binding loop}
// ^error{The binding for the property 'layoutinfo-h' is part of a binding loop} // FIXME: That's an internal property, but people might understand
// ^^error{The binding for the property 'min-width' is part of a binding loop}
Rectangle {
width: parent.min_width;
// ^error{The binding for the property 'width' is part of a binding loop}
@ -37,8 +37,8 @@ Test := Rectangle {
l := HorizontalLayout {
// ^error{The binding for the property 'layoutinfo_h' is part of a binding loop} // FIXME: That's an internal property, but people might understand
// ^^error{The binding for the property 'preferred_width' is part of a binding loop}
// ^error{The binding for the property 'layoutinfo-h' is part of a binding loop} // FIXME: That's an internal property, but people might understand
// ^^error{The binding for the property 'preferred-width' is part of a binding loop}
Text {
text: "hello \{l.preferred-width/1px}x\{l.preferred-height/1px}";
// ^error{The binding for the property 'text' is part of a binding loop}
@ -46,8 +46,8 @@ Test := Rectangle {
}
tc := TC {
// ^error{The binding for the property 'preferred_width' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo_h' is part of a binding loop}
// ^error{The binding for the property 'preferred-width' is part of a binding loop}
// ^^error{The binding for the property 'layoutinfo-h' is part of a binding loop}
width: preferred-width;
// ^error{The binding for the property 'width' is part of a binding loop}
}

View file

@ -12,9 +12,9 @@ LICENSE END */
Test := Rectangle {
property <image> source;
GridLayout {
// ^error{The binding for the property 'layout_cache_h' is part of a binding loop}
// ^error{The binding for the property 'layout-cache-h' is part of a binding loop}
// ^^error{The binding for the property 'width' is part of a binding loop}
// ^^^error{The binding for the property 'layout_cache_v' is part of a binding loop}
// ^^^error{The binding for the property 'layout-cache-v' is part of a binding loop}
// ^^^^error{The binding for the property 'height' is part of a binding loop}
Image {
source: root.source;

View file

@ -9,11 +9,11 @@
LICENSE END */
SuperSimple := Rectangle {
drop-shadow-color: #00000080;
// ^warning{The drop_shadow_color property cannot be used on the root element, the shadow will not be visible}
// ^warning{The drop-shadow-color property cannot be used on the root element, the shadow will not be visible}
Text {
drop-shadow-color: black;
// ^error{The drop_shadow_color property is only supported on Rectangle and Clip elements right now}
// ^error{The drop-shadow-color property is only supported on Rectangle and Clip elements right now}
}
}

View file

@ -18,7 +18,7 @@ X := Rectangle {
// ^error{Duplicated property binding}
not_exist <=> 12phx;
// ^error{Unknown property not_exist in Rectangle}
// ^error{Unknown property not-exist in Rectangle}
property <int> foo: 12;
foo: 13;

View file

@ -17,6 +17,6 @@ X := Rectangle {
callback xxx() -> string;
xxx => {
return 42phx;
// ^error{Cannot convert physical_length to string. Divide by 1phx to convert to a plain number}
// ^error{Cannot convert physical-length to string. Divide by 1phx to convert to a plain number}
}
}

View file

@ -34,13 +34,13 @@ SubElements := Rectangle {
}
does_not_exist => {
// ^error{'does_not_exist' is not a callback in Rectangle}
// ^error{'does-not-exist' is not a callback in Rectangle}
root.does_not_exist();
}
foobar() => { foobar() }
callback_with_arg(a, b, c, d) => { }
// ^error{'callback_with_arg' only has 2 arguments, but 4 were provided}
// ^error{'callback-with-arg' only has 2 arguments, but 4 were provided}
}

View file

@ -20,7 +20,7 @@ TestCase := Rectangle {
transitions [
in does_not_exist: {
// ^error{State 'does_not_exist' does not exist}
// ^error{State 'does-not-exist' does not exist}
animate * { }
}
in checked: {

View file

@ -26,7 +26,7 @@ export Demo := Window {
t.y: 100px;
// ^error{Cannot change the property 'y' in a state because it is initialized with a two-way binding}
some_prop: "plop";
// ^error{Cannot change the property 'some_prop' in a state because it is initialized with a two-way binding}
// ^error{Cannot change the property 'some-prop' in a state because it is initialized with a two-way binding}
}
]
}

View file

@ -23,7 +23,7 @@ SuperSimple := Rectangle {
Rectangle {
background: blue;
foo_bar: blue;
// ^error{Unknown property foo_bar in Rectangle}
// ^error{Unknown property foo-bar in Rectangle}
}
}
@ -45,7 +45,7 @@ SuperSimple := Rectangle {
Rectangle {
foo_bar: blue;
// ^error{Unknown property foo_bar in Rectangle}
// ^error{Unknown property foo-bar in Rectangle}
}
NativeLineEdit { }

View file

@ -12,13 +12,13 @@ Test := Rectangle {
GridLayout {
Rectangle {
height: 42px;
// ^error{Cannot specify both 'height' and 'min_height'}
// ^error{Cannot specify both 'height' and 'min-height'}
min-height: 42px;
max-width: 42px;
}
Rectangle {
width: 42px;
// ^error{Cannot specify both 'width' and 'max_width'}
// ^error{Cannot specify both 'width' and 'max-width'}
min-height: 42px;
max-width: 42px;
}

View file

@ -22,8 +22,8 @@ Xxx := Rectangle {
}
minimum-height: root.maximum-width;
// ^warning{The property 'minimum_height' has been deprecated. Please use 'min_height' instead}
// ^^warning{The property 'maximum_width' has been deprecated. Please use 'max_width' instead}
// ^warning{The property 'minimum-height' has been deprecated. Please use 'min-height' instead}
// ^^warning{The property 'maximum-width' has been deprecated. Please use 'max-width' instead}
callback not_called;
not_called() => {

View file

@ -65,7 +65,7 @@ Hello := Rectangle {
y: pp.b;
// ^error{Cannot convert string to length}
property<int> ggg: pp;
// ^error{Cannot convert \{ a: physical_length,b: string,\} to int}
// ^error{Cannot convert \{ a: physical-length,b: string,\} to int}
}

View file

@ -37,6 +37,6 @@ X := Rectangle {
x <=> self.loop_on_x;
// ^error{The binding for the property 'x' is part of a binding loop}
property <length> loop_on_x <=> x;
// ^error{The binding for the property 'loop_on_x' is part of a binding loop}
// ^error{The binding for the property 'loop-on-x' is part of a binding loop}
}
}

View file

@ -11,20 +11,20 @@ LICENSE END */
X := Rectangle {
property infer_loop <=> infer_loop2;
// ^error{Could not infer type of property 'infer_loop'}
// ^error{Could not infer type of property 'infer-loop'}
property infer_loop2 <=> infer_loop3;
// ^error{Could not infer type of property 'infer_loop2'}
// ^error{Could not infer type of property 'infer-loop2'}
property infer_loop3 <=> infer_loop;
// ^error{Could not infer type of property 'infer_loop3'}
// ^error{Could not infer type of property 'infer-loop3'}
// ^^error{Unknown unqualified identifier 'infer_loop'}
// ^^^error{The expression in a two way binding must be a property reference}
property infer_error <=> r.infer_error;
// ^error{Could not infer type of property 'infer_error'}
// ^error{Could not infer type of property 'infer-error'}
r := Rectangle {
property infer_error <=> 0;
// ^error{The expression in a two way binding must be a property reference}
// ^^error{Could not infer type of property 'infer_error'}
// ^^error{Could not infer type of property 'infer-error'}
}
property auto_background <=> background;

View file

@ -24,19 +24,19 @@ pub(crate) const RESERVED_GEOMETRY_PROPERTIES: &[(&str, Type)] = &[
];
const RESERVED_LAYOUT_PROPERTIES: &[(&str, Type)] = &[
("min_width", Type::LogicalLength),
("min_height", Type::LogicalLength),
("max_width", Type::LogicalLength),
("max_height", Type::LogicalLength),
("min-width", Type::LogicalLength),
("min-height", Type::LogicalLength),
("max-width", Type::LogicalLength),
("max-height", Type::LogicalLength),
("padding", Type::LogicalLength),
("padding_left", Type::LogicalLength),
("padding_right", Type::LogicalLength),
("padding_top", Type::LogicalLength),
("padding_bottom", Type::LogicalLength),
("preferred_width", Type::LogicalLength),
("preferred_height", Type::LogicalLength),
("horizontal_stretch", Type::Float32),
("vertical_stretch", Type::Float32),
("padding-left", Type::LogicalLength),
("padding-right", Type::LogicalLength),
("padding-top", Type::LogicalLength),
("padding-bottom", Type::LogicalLength),
("preferred-width", Type::LogicalLength),
("preferred-height", Type::LogicalLength),
("horizontal-stretch", Type::Float32),
("vertical-stretch", Type::Float32),
("col", Type::Int32),
("row", Type::Int32),
("colspan", Type::Int32),
@ -50,10 +50,10 @@ const RESERVED_OTHER_PROPERTIES: &[(&str, Type)] = &[
];
pub(crate) const RESERVED_DROP_SHADOW_PROPERTIES: &[(&str, Type)] = &[
("drop_shadow_offset_x", Type::LogicalLength),
("drop_shadow_offset_y", Type::LogicalLength),
("drop_shadow_blur", Type::LogicalLength),
("drop_shadow_color", Type::Color),
("drop-shadow-offset-x", Type::LogicalLength),
("drop-shadow-offset-y", Type::LogicalLength),
("drop-shadow-blur", Type::LogicalLength),
("drop-shadow-color", Type::Color),
];
/// list of reserved property injected in every item
@ -65,7 +65,7 @@ pub fn reserved_properties() -> impl Iterator<Item = (&'static str, Type)> {
.chain(RESERVED_DROP_SHADOW_PROPERTIES.iter())
.map(|(k, v)| (*k, v.clone()))
.chain(std::array::IntoIter::new([
("forward_focus", Type::ElementReference),
("forward-focus", Type::ElementReference),
("focus", BuiltinFunction::SetFocusItem.ty()),
]))
}
@ -83,10 +83,10 @@ pub fn reserved_property(name: &str) -> PropertyLookupResult {
if let Some(a) = name.strip_prefix(pre) {
for suf in &["width", "height"] {
if let Some(b) = a.strip_suffix(suf) {
if b == "imum_" {
if b == "imum-" {
return PropertyLookupResult {
property_type: Type::LogicalLength,
resolved_name: format!("{}_{}", pre, suf).into(),
resolved_name: format!("{}-{}", pre, suf).into(),
};
}
}
@ -164,11 +164,11 @@ impl TypeRegister {
declare_enum("TextHorizontalAlignment", &["left", "center", "right"]);
declare_enum("TextVerticalAlignment", &["top", "center", "bottom"]);
declare_enum("TextWrap", &["no_wrap", "word_wrap"]);
declare_enum("TextWrap", &["no-wrap", "word-wrap"]);
declare_enum("TextOverflow", &["clip", "elide"]);
declare_enum(
"LayoutAlignment",
&["stretch", "center", "start", "end", "space_between", "space_around"],
&["stretch", "center", "start", "end", "space-between", "space-around"],
);
declare_enum("ImageFit", &["fill", "contain", "cover"]);
declare_enum("EventResult", &["reject", "accept"]);

View file

@ -39,6 +39,7 @@ pub fn sixtyfps_element(input: TokenStream) -> TokenStream {
};
let mut pub_prop_field_names = Vec::new();
let mut pub_prop_field_names_normalized = Vec::new();
let mut pub_prop_field_types = Vec::new();
let mut property_names = Vec::new();
let mut property_visibility = Vec::new();
@ -47,6 +48,7 @@ pub fn sixtyfps_element(input: TokenStream) -> TokenStream {
if let Some(property_type) = property_type(&field.ty) {
let name = field.ident.as_ref().unwrap();
if matches!(field.vis, syn::Visibility::Public(_)) {
pub_prop_field_names_normalized.push(normalize_identifier(name));
pub_prop_field_names.push(name);
pub_prop_field_types.push(&field.ty);
}
@ -73,14 +75,18 @@ pub fn sixtyfps_element(input: TokenStream) -> TokenStream {
})
.map(|f| (f.ident.as_ref().unwrap(), &f.ty))
.unzip();
let plain_field_names_normalized =
plain_field_names.iter().map(|f| normalize_identifier(*f)).collect::<Vec<_>>();
let mut callback_field_names = Vec::new();
let mut callback_field_names_normalized = Vec::new();
let mut callback_args = Vec::new();
let mut callback_rets = Vec::new();
for field in fields {
if let Some((arg, ret)) = callback_arg(&field.ty) {
if matches!(field.vis, syn::Visibility::Public(_)) {
let name = field.ident.as_ref().unwrap();
callback_field_names_normalized.push(normalize_identifier(name));
callback_field_names.push(name);
callback_args.push(arg);
callback_rets.push(ret);
@ -101,21 +107,21 @@ pub fn sixtyfps_element(input: TokenStream) -> TokenStream {
vec![#( {
const O : MaybeAnimatedPropertyInfoWrapper<#item_name, #pub_prop_field_types> =
MaybeAnimatedPropertyInfoWrapper(#item_name::FIELD_OFFSETS.#pub_prop_field_names);
(stringify!(#pub_prop_field_names), (&O).as_property_info())
(#pub_prop_field_names_normalized, (&O).as_property_info())
} ),*]
}
fn fields<Value: ValueType>() -> Vec<(&'static str, &'static dyn FieldInfo<Self, Value>)> {
vec![#( {
const O : const_field_offset::FieldOffset<#item_name, #plain_field_types, const_field_offset::AllowPin> =
#item_name::FIELD_OFFSETS.#plain_field_names;
(stringify!(#plain_field_names), &O as &'static dyn FieldInfo<Self, Value>)
(#plain_field_names_normalized, &O as &'static dyn FieldInfo<Self, Value>)
} ),*]
}
fn callbacks<Value: ValueType>() -> Vec<(&'static str, &'static dyn CallbackInfo<Self, Value>)> {
vec![#( {
const O : const_field_offset::FieldOffset<#item_name, Callback<#callback_args, #callback_rets>, const_field_offset::AllowPin> =
#item_name::FIELD_OFFSETS.#callback_field_names;
(stringify!(#callback_field_names), &O as &'static dyn CallbackInfo<Self, Value>)
(#callback_field_names_normalized, &O as &'static dyn CallbackInfo<Self, Value>)
} ),*]
}
}
@ -131,6 +137,10 @@ pub fn sixtyfps_element(input: TokenStream) -> TokenStream {
.into()
}
fn normalize_identifier(name: &syn::Ident) -> String {
name.to_string().replace('_', "-")
}
// Try to match `Property<Foo>` on the syn tree and return Foo if found
fn property_type(ty: &syn::Type) -> Option<&syn::Type> {
if let syn::Type::Path(syn::TypePath { path: syn::Path { segments, .. }, .. }) = ty {

View file

@ -12,6 +12,7 @@ use core::convert::TryInto;
use sixtyfps_compilerlib::langtype::Type as LangType;
use sixtyfps_corelib::graphics::Image;
use sixtyfps_corelib::{Brush, PathData, SharedString, SharedVector};
use std::borrow::Cow;
use std::collections::HashMap;
use std::iter::FromIterator;
use std::path::{Path, PathBuf};
@ -281,7 +282,9 @@ macro_rules! declare_value_enum_conversion {
return Err(());
}
<$ty>::from_str(value.as_str()).map_err(|_| ())
<$ty>::from_str(value.as_str())
.or_else(|_| <$ty>::from_str(&value.as_str().replace('-', "_")))
.map_err(|_| ())
}
_ => Err(()),
}
@ -352,6 +355,15 @@ impl TryInto<sixtyfps_corelib::Color> for Value {
}
}
/// Normalize the identifier to use dashes
fn normalize_identifier(ident: &str) -> Cow<'_, str> {
if ident.contains('_') {
ident.replace('_', "-").into()
} else {
ident.into()
}
}
/// This type represents a runtime instance of structure in `.60`.
///
/// This can either be an instance of a name structure introduced
@ -378,12 +390,16 @@ pub struct Struct(HashMap<String, Value>);
impl Struct {
/// Get the value for a given struct field
pub fn get_field(&self, name: &str) -> Option<&Value> {
self.0.get(name)
self.0.get(&*normalize_identifier(name))
}
/// Set the value of a given struct field
pub fn set_field(&mut self, name: String, value: Value) {
if name.contains('_') {
self.0.insert(name.replace('_', "-"), value);
} else {
self.0.insert(name, value);
}
}
/// Iterate over all the fields in this struct
pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> {
@ -393,7 +409,11 @@ impl Struct {
impl FromIterator<(String, Value)> for Struct {
fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
Self(iter.into_iter().collect())
Self(
iter.into_iter()
.map(|(s, v)| (if s.contains('_') { s.replace('_', "-") } else { s }, v))
.collect(),
)
}
}
@ -700,7 +720,7 @@ impl ComponentInstance {
generativity::make_guard!(guard);
let comp = self.inner.unerase(guard);
comp.description()
.get_property(comp.borrow(), name)
.get_property(comp.borrow(), &normalize_identifier(name))
.map_err(|()| GetPropertyError::NoSuchProperty)
}
@ -709,7 +729,7 @@ impl ComponentInstance {
generativity::make_guard!(guard);
let comp = self.inner.unerase(guard);
comp.description()
.set_property(comp.borrow(), name, value)
.set_property(comp.borrow(), &normalize_identifier(name), value)
.map_err(|()| todo!("set_property don't return the right error type"))
}
@ -754,7 +774,7 @@ impl ComponentInstance {
generativity::make_guard!(guard);
let comp = self.inner.unerase(guard);
comp.description()
.set_callback_handler(comp.borrow(), name, Box::new(callback))
.set_callback_handler(comp.borrow(), &normalize_identifier(name), Box::new(callback))
.map_err(|()| SetCallbackError::NoSuchCallback)
}
@ -765,7 +785,9 @@ impl ComponentInstance {
pub fn invoke_callback(&self, name: &str, args: &[Value]) -> Result<Value, CallCallbackError> {
generativity::make_guard!(guard);
let comp = self.inner.unerase(guard);
comp.description().invoke_callback(comp.borrow(), name, args).map_err(|()| todo!())
comp.description()
.invoke_callback(comp.borrow(), &normalize_identifier(name), args)
.map_err(|()| todo!())
}
/// Marks the window of this component to be shown on the screen. This registers

View file

@ -85,7 +85,7 @@ try {
instance.test_callback();
assert(false);
} catch(e) {
assert.equal(e.toString(), "Error: test_callback expect 1 arguments, but 0 where provided");
assert.equal(e.toString(), "Error: test-callback expect 1 arguments, but 0 where provided");
}
assert.equal(instance.callback_emission_count, 0);

View file

@ -66,6 +66,7 @@ let super_player = { name: "Super Player", score: 99, energy_level: 0.4 };
instance.player_2 = super_player;
assert.equal(instance.player_2.name, "Super Player");
assert.equal(instance.player_2_score, 99);
assert.equal(instance.player_2.energy_level, 0.4);
```
*/