Don't generate a native setter for out property

This commit is contained in:
Olivier Goffart 2022-11-09 14:56:56 +01:00 committed by Olivier Goffart
parent 8a7c9bc53d
commit 5b44cc54d9
7 changed files with 66 additions and 44 deletions

View file

@ -1779,12 +1779,12 @@ fn generate_public_api_for_properties(
ctx: &EvaluationContext,
) -> Vec<Declaration> {
let mut declarations = Vec::new();
for (p, (ty, r)) in public_properties.iter() {
let prop_ident = ident(p);
for p in public_properties.iter() {
let prop_ident = ident(&p.name);
let access = access_member(r, ctx);
let access = access_member(&p.prop, ctx);
if let Type::Callback { args, return_type } = ty {
if let Type::Callback { args, return_type } = &p.ty {
let param_types = args.iter().map(|t| t.cpp_type().unwrap()).collect::<Vec<_>>();
let return_type = return_type.as_ref().map_or("void".into(), |t| t.cpp_type().unwrap());
let callback_emitter = vec![
@ -1796,7 +1796,7 @@ fn generate_public_api_for_properties(
),
];
declarations.push(Declaration::Function(Function {
name: format!("invoke_{}", ident(p)),
name: format!("invoke_{}", ident(&p.name)),
signature: format!(
"({}) const -> {}",
param_types
@ -1810,7 +1810,7 @@ fn generate_public_api_for_properties(
..Default::default()
}));
declarations.push(Declaration::Function(Function {
name: format!("on_{}", ident(p)),
name: format!("on_{}", ident(&p.name)),
template_parameters: Some("typename Functor".into()),
signature: "(Functor && callback_handler) const".into(),
statements: Some(vec![
@ -1820,7 +1820,7 @@ fn generate_public_api_for_properties(
..Default::default()
}));
} else {
let cpp_property_type = ty.cpp_type().expect("Invalid type in public properties");
let cpp_property_type = p.ty.cpp_type().expect("Invalid type in public properties");
let prop_getter: Vec<String> = vec![
"[[maybe_unused]] auto self = this;".into(),
format!("return {}.get();", access),
@ -1832,16 +1832,18 @@ fn generate_public_api_for_properties(
..Default::default()
}));
let prop_setter: Vec<String> = vec![
"[[maybe_unused]] auto self = this;".into(),
property_set_value_code(r, "value", ctx) + ";",
];
declarations.push(Declaration::Function(Function {
name: format!("set_{}", &prop_ident),
signature: format!("(const {} &value) const", &cpp_property_type),
statements: Some(prop_setter),
..Default::default()
}));
if !p.read_only {
let prop_setter: Vec<String> = vec![
"[[maybe_unused]] auto self = this;".into(),
property_set_value_code(&p.prop, "value", ctx) + ";",
];
declarations.push(Declaration::Function(Function {
name: format!("set_{}", &prop_ident),
signature: format!("(const {} &value) const", &cpp_property_type),
statements: Some(prop_setter),
..Default::default()
}));
}
}
}
declarations

View file

@ -524,11 +524,11 @@ fn public_api(
ctx: &EvaluationContext,
) -> TokenStream {
let mut property_and_callback_accessors: Vec<TokenStream> = vec![];
for (p, (ty, r)) in public_properties {
let prop_ident = ident(p);
let prop = access_member(r, ctx);
for p in public_properties {
let prop_ident = ident(&p.name);
let prop = access_member(&p.prop, ctx);
if let Type::Callback { args, return_type } = ty {
if let Type::Callback { args, return_type } = &p.ty {
let callback_args =
args.iter().map(|a| rust_primitive_type(a).unwrap()).collect::<Vec<_>>();
let return_type =
@ -556,12 +556,11 @@ fn public_api(
}
));
} else {
let rust_property_type = rust_primitive_type(ty).unwrap();
let rust_property_type = rust_primitive_type(&p.ty).unwrap();
let getter_ident = format_ident!("get_{}", prop_ident);
let setter_ident = format_ident!("set_{}", prop_ident);
let prop_expression = primitive_property_value(ty, prop);
let prop_expression = primitive_property_value(&p.ty, prop);
property_and_callback_accessors.push(quote!(
#[allow(dead_code)]
@ -573,16 +572,19 @@ fn public_api(
}
));
let set_value = property_set_value_tokens(r, quote!(value), ctx);
property_and_callback_accessors.push(quote!(
#[allow(dead_code)]
pub fn #setter_ident(&self, value: #rust_property_type) {
#[allow(unused_imports)]
use slint::private_unstable_api::re_exports::*;
let _self = #self_init;
#set_value
}
));
if !p.read_only {
let setter_ident = format_ident!("set_{}", prop_ident);
let set_value = property_set_value_tokens(&p.prop, quote!(value), ctx);
property_and_callback_accessors.push(quote!(
#[allow(dead_code)]
pub fn #setter_ident(&self, value: #rust_property_type) {
#[allow(unused_imports)]
use slint::private_unstable_api::re_exports::*;
let _self = #self_init;
#set_value
}
));
}
}
}

View file

@ -352,4 +352,11 @@ impl PublicComponent {
}
}
pub type PublicProperties = BTreeMap<String, (Type, PropertyReference)>;
#[derive(Debug, Clone)]
pub struct PublicProperty {
pub name: String,
pub ty: Type,
pub prop: PropertyReference,
pub read_only: bool,
}
pub type PublicProperties = Vec<PublicProperty>;

View file

@ -7,7 +7,7 @@ use crate::expression_tree::Expression as tree_Expression;
use crate::langtype::{ElementType, Type};
use crate::llr::item_tree::*;
use crate::namedreference::NamedReference;
use crate::object_tree::{Component, ElementRc};
use crate::object_tree::{Component, ElementRc, PropertyVisibility};
use std::collections::HashMap;
use std::rc::Rc;
@ -661,7 +661,12 @@ fn public_properties(
.map(|(p, c)| {
let property_reference = mapping
.map_property_reference(&NamedReference::new(&component.root_element, p), state);
(p.clone(), (c.property_type.clone(), property_reference))
PublicProperty {
name: p.clone(),
ty: c.property_type.clone(),
prop: property_reference,
read_only: c.visibility == PropertyVisibility::Output,
}
})
.collect()
}

View file

@ -11,13 +11,13 @@ pub fn count_property_use(root: &PublicComponent) {
// Visit the root properties that are used.
// 1. the public properties
let root_ctx = EvaluationContext::new_sub_component(root, &root.item_tree.root, (), None);
for (_, pr) in root.public_properties.values() {
visit_property(pr, &root_ctx);
for p in root.public_properties.iter() {
visit_property(&p.prop, &root_ctx);
}
for g in root.globals.iter().filter(|g| g.exported) {
let ctx = EvaluationContext::new_global(root, g, ());
for (_, pr) in g.public_properties.values() {
visit_property(pr, &ctx);
for p in g.public_properties.iter() {
visit_property(&p.prop, &ctx);
}
}

View file

@ -833,6 +833,7 @@ impl Element {
PropertyDeclaration {
property_type: Type::InferredCallback,
node: Some(Either::Right(sig_decl)),
visibility: PropertyVisibility::InOut,
..Default::default()
},
);
@ -848,6 +849,7 @@ impl Element {
PropertyDeclaration {
property_type: Type::Callback { return_type, args },
node: Some(Either::Right(sig_decl)),
visibility: PropertyVisibility::InOut,
..Default::default()
},
);

View file

@ -6,7 +6,7 @@
use std::rc::Rc;
use crate::diagnostics::{BuildDiagnostics, DiagnosticLevel};
use crate::object_tree::{Component, Document};
use crate::object_tree::{Component, Document, PropertyVisibility};
pub fn check_public_api(doc: &Document, diag: &mut BuildDiagnostics) {
check_public_api_component(&doc.root_component, diag);
@ -27,8 +27,12 @@ fn check_public_api_component(root_component: &Rc<Component>, diag: &mut BuildDi
let mut pa = root_elem.property_analysis.borrow_mut();
root_elem.property_declarations.iter_mut().for_each(|(n, d)| {
if d.property_type.ok_for_public_api() {
d.expose_in_public_api = true;
pa.entry(n.to_string()).or_default().is_set = true;
if d.visibility != PropertyVisibility::Private {
d.expose_in_public_api = true;
if d.visibility != PropertyVisibility::Output {
pa.entry(n.to_string()).or_default().is_set = true;
}
}
} else {
diag.push_diagnostic(
format!("Properties of type {} are not supported yet for public API. The property will not be exposed", d.property_type),