Skip to content

Commit

Permalink
Add HashSet of flags to ParsedQPoperty for optional getters and setters
Browse files Browse the repository at this point in the history
  • Loading branch information
BenFordTytherington committed Jul 9, 2024
1 parent cbd69fd commit a9fa32e
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 3 deletions.
6 changes: 5 additions & 1 deletion crates/cxx-qt-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
[package]
name = "cxx-qt-gen"
version.workspace = true
authors = ["Andrew Hayzen <[email protected]>", "Gerhard de Clercq <[email protected]>", "Leon Matthes <[email protected]>"]
authors = [
"Andrew Hayzen <[email protected]>",
"Gerhard de Clercq <[email protected]>",
"Leon Matthes <[email protected]>",
]
edition.workspace = true
license.workspace = true
description = "Code generation for integrating `cxx-qt` into higher level tools"
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt-gen/src/generator/cpp/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ mod tests {
ParsedQProperty {
ident: format_ident!("trivial_property"),
ty: parse_quote! { i32 },
flags: Default::default(),
},
ParsedQProperty {
ident: format_ident!("opaque_property"),
ty: parse_quote! { UniquePtr<QColor> },
flags: Default::default(),
},
];
let qobject_idents = create_qobjectname();
Expand Down Expand Up @@ -358,6 +360,7 @@ mod tests {
let properties = vec![ParsedQProperty {
ident: format_ident!("mapped_property"),
ty: parse_quote! { A },
flags: Default::default(),
}];
let qobject_idents = create_qobjectname();

Expand Down
1 change: 1 addition & 0 deletions crates/cxx-qt-gen/src/generator/naming/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub mod tests {
let property = ParsedQProperty {
ident: format_ident!("my_property"),
ty,
flags: Default::default(),
};
QPropertyNames::from(&property)
}
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt-gen/src/generator/rust/property/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,17 @@ mod tests {
ParsedQProperty {
ident: format_ident!("trivial_property"),
ty: parse_quote! { i32 },
flags: Default::default(),
},
ParsedQProperty {
ident: format_ident!("opaque_property"),
ty: parse_quote! { UniquePtr<QColor> },
flags: Default::default(),
},
ParsedQProperty {
ident: format_ident!("unsafe_property"),
ty: parse_quote! { *mut T },
flags: Default::default(),
},
];
let qobject_idents = create_qobjectname();
Expand Down
83 changes: 81 additions & 2 deletions crates/cxx-qt-gen/src/parser/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use syn::{parse::ParseStream, Attribute, Ident, Result, Token, Type};
use std::collections::HashSet;

use syn::{parse::ParseStream, punctuated::Punctuated, Attribute, Ident, Result, Token, Type};

#[derive(Debug, Eq, PartialEq, Hash)]
pub enum QPropertyFlag {
Read,
Write,
Notify,
}

/// Describes a single Q_PROPERTY for a struct
pub struct ParsedQProperty {
/// The [syn::Ident] of the property
pub ident: Ident,
/// The [syn::Type] of the property
pub ty: Type,
/// HashSet of [QPropertyFlag]s which were specified
pub flags: HashSet<QPropertyFlag>,
}

impl ParsedQProperty {
Expand All @@ -20,10 +31,42 @@ impl ParsedQProperty {
let _comma = input.parse::<Token![,]>()?;
let ident = input.parse()?;

if input.is_empty() {
// No flags so return with empty HashSet
return Ok(Self {
ident,
ty,
flags: Default::default(),
});
}

let _comma = input.parse::<Token![,]>()?; // Start of final identifiers

// TODO: Allow parser to store pairs of items e.g read = get_value, Might be useful to use Meta::NameValue
let punctuated_flags: Punctuated<Ident, Token![,]> =
Punctuated::parse_terminated(input)?;

let flags: Vec<Ident> = punctuated_flags.into_iter().collect(); // Removes the commas while collecting into Vec

let mut flags_set: HashSet<QPropertyFlag> = HashSet::new();

for identifier in flags {
match identifier.to_string().as_str() {
"read" => flags_set.insert(QPropertyFlag::Read),
"write" => flags_set.insert(QPropertyFlag::Write),
"notify" => flags_set.insert(QPropertyFlag::Notify),
_ => panic!("Invalid Token"), // TODO: might not be a good idea to error here
};
}

// TODO: later we'll need to parse setters and getters here
// which are key-value, hence this not being parsed as a list

Ok(Self { ident, ty })
Ok(Self {
ident,
ty,
flags: flags_set,
})
})
}
}
Expand All @@ -46,6 +89,42 @@ mod tests {
assert_eq!(property.ty, parse_quote! { T });
}

#[test]
fn test_parse_read_flag() {
let mut input: ItemStruct = parse_quote! {
#[qproperty(T, name, read)]
struct MyStruct;
};
let property = ParsedQProperty::parse(input.attrs.remove(0)).unwrap();
assert_eq!(property.ident, format_ident!("name"));
assert_eq!(property.ty, parse_quote! { T });
assert!(property.flags.contains(&QPropertyFlag::Read));
}

#[test]
fn test_parse_all_flags() {
let mut input: ItemStruct = parse_quote! {
#[qproperty(T, name, read, write, notify)]
struct MyStruct;
};
let property = ParsedQProperty::parse(input.attrs.remove(0)).unwrap();
assert_eq!(property.ident, format_ident!("name"));
assert_eq!(property.ty, parse_quote! { T });
assert!(property.flags.contains(&QPropertyFlag::Read));
assert!(property.flags.contains(&QPropertyFlag::Write));
assert!(property.flags.contains(&QPropertyFlag::Notify));
}

#[test]
#[should_panic]
fn test_parse_invalid_flags() {
let mut input: ItemStruct = parse_quote! {
#[qproperty(T, name, read, write, A)]
struct MyStruct;
};
let property = ParsedQProperty::parse(input.attrs.remove(0)).unwrap();
}

#[test]
fn test_parse_property_arg_extra() {
let mut input: ItemStruct = parse_quote! {
Expand Down

0 comments on commit a9fa32e

Please sign in to comment.