Skip to content

Commit 7f44b7a

Browse files
committed
feat(pbxproj): auto set fs_reference parent
1 parent 0e5706a commit 7f44b7a

File tree

4 files changed

+81
-25
lines changed

4 files changed

+81
-25
lines changed

src/pbxproj/object/collection.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl PBXObjectCollection {
5858
.collect()
5959
}
6060

61-
fn fs_references<'a>(
61+
pub(crate) fn get_fs_references<'a>(
6262
&'a self,
6363
predict: fn(Ref<PBXFSReference>) -> bool,
6464
) -> Vec<(String, Rc<RefCell<PBXFSReference>>)> {
@@ -74,9 +74,16 @@ impl PBXObjectCollection {
7474
.collect()
7575
}
7676

77+
pub(crate) fn fs_references<'a>(&'a self) -> Vec<(String, Rc<RefCell<PBXFSReference>>)> {
78+
self.iter()
79+
.map(|(k, o)| Some((k.clone(), o.as_pbxfs_reference()?.clone())))
80+
.flatten()
81+
.collect()
82+
}
83+
7784
/// Get all PBXGroup
7885
pub fn groups<'a>(&'a self) -> Vec<(String, Rc<RefCell<PBXFSReference>>)> {
79-
self.fs_references(|fs_reference| fs_reference.is_group())
86+
self.get_fs_references(|fs_reference| fs_reference.is_group())
8087
}
8188

8289
/// Get all PBXProject
@@ -89,7 +96,7 @@ impl PBXObjectCollection {
8996

9097
/// Get all files
9198
pub fn files<'a>(&'a self) -> Vec<(String, Rc<RefCell<PBXFSReference>>)> {
92-
self.fs_references(|fs_reference| fs_reference.is_file())
99+
self.get_fs_references(|fs_reference| fs_reference.is_file())
93100
}
94101

95102
/// Get all PBXBuildFile

src/pbxproj/object/fs/mod.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ mod kind;
22
mod obj;
33
mod setget;
44
mod source_tree;
5+
56
use super::*;
6-
use std::{cell::RefCell, collections::HashSet, rc::Rc};
7+
use std::{
8+
cell::RefCell,
9+
collections::HashSet,
10+
rc::{Rc, Weak},
11+
};
712

813
pub use kind::*;
914
pub use source_tree::*;
@@ -50,22 +55,11 @@ pub struct PBXFSReference {
5055
/// Version group type. (only relevant for XCVersionGroup)
5156
version_group_type: Option<String>,
5257

53-
pub(crate) parent_reference: Option<String>,
58+
parent: Weak<RefCell<Self>>,
5459
pub(crate) objects: WeakPBXObjectCollection,
5560
}
5661

5762
impl PBXFSReference {
58-
/// Get a reference to the pbxfile element's parent reference.
59-
#[must_use]
60-
pub fn parent(&self) -> Option<Rc<RefCell<PBXFSReference>>> {
61-
self.objects
62-
.upgrade()?
63-
.borrow()
64-
.get(self.parent_reference.as_ref()?)?
65-
.as_pbxfs_reference()
66-
.map(|r| r.clone())
67-
}
68-
6963
/// Get Group children.
7064
/// WARN: This will return empty if self is of type file
7165
pub fn children(&self) -> Vec<Rc<RefCell<PBXFSReference>>> {
@@ -105,6 +99,27 @@ impl PBXFSReference {
10599
}
106100
})
107101
}
102+
103+
pub(crate) fn assign_parent_to_children(&self, this: Weak<RefCell<Self>>) {
104+
if self.is_group() {
105+
self.children().into_iter().for_each(|o| {
106+
let mut fs_reference = o.borrow_mut();
107+
fs_reference.parent = this.clone();
108+
fs_reference.assign_parent_to_children(Rc::downgrade(&o))
109+
});
110+
}
111+
}
112+
113+
/// Set the pbxfsreference's parent.
114+
pub fn set_parent(&mut self, parent: Weak<RefCell<Self>>) {
115+
self.parent = parent;
116+
}
117+
118+
/// Get a reference to the pbxfsreference's parent.
119+
#[must_use]
120+
pub fn parent(&self) -> Option<Rc<RefCell<Self>>> {
121+
self.parent.upgrade()
122+
}
108123
}
109124

110125
impl Eq for PBXFSReference {}
@@ -114,7 +129,6 @@ impl PartialEq for PBXFSReference {
114129
&& self.source_tree == other.source_tree
115130
&& self.path == other.path
116131
&& self.name == other.name
117-
&& self.parent_reference == other.parent_reference
118132
&& self.children_references == other.children_references
119133
&& self.current_version_reference == other.current_version_reference
120134
&& self.version_group_type == other.version_group_type
@@ -134,3 +148,29 @@ impl PartialEq for PBXFSReference {
134148
== other.plist_structure_definition_identifier
135149
}
136150
}
151+
152+
#[test]
153+
fn test_parent() {
154+
use crate::pbxproj::test_demo_file;
155+
let project = test_demo_file!(demo1);
156+
let main_group = project
157+
.objects()
158+
.projects()
159+
.first()
160+
.unwrap()
161+
.1
162+
.borrow()
163+
.main_group();
164+
165+
let main_group = main_group.borrow();
166+
167+
let source_group = main_group.get_subgroup("Source").unwrap();
168+
let source_group = source_group.borrow();
169+
let parent = source_group.parent();
170+
println!("{:#?}", main_group);
171+
172+
assert_eq!(
173+
parent.unwrap().borrow().children_references(),
174+
main_group.children_references()
175+
)
176+
}

src/pbxproj/object/fs/obj.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ impl PBXObjectExt for PBXFSReference {
2626
.remove_vec("children")
2727
.map(|v| v.try_into_vec_strings().ok().map(|v| HashSet::from_iter(v)))
2828
.flatten(),
29-
parent_reference: None,
29+
parent: Weak::new(),
3030
file_encoding: value.remove_number("fileEncoding"),
3131
explicit_file_type: value.remove_string("explicitFileType"),
3232
last_known_file_type: value.remove_string("lastKnownFileType"),

src/pbxproj/rep.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ impl TryFrom<PBXHashMap> for PBXRootObject {
8484
.collect::<HashMap<_, _>>();
8585

8686
refcell.borrow_mut().set_inner(objects);
87+
refcell
88+
.borrow()
89+
.groups()
90+
.into_iter()
91+
.for_each(|(_, group)| {
92+
let fs_reference = group.borrow_mut();
93+
fs_reference.assign_parent_to_children(Rc::downgrade(&group))
94+
});
8795

8896
Ok(Self {
8997
archive_version,
@@ -138,27 +146,28 @@ fn test_parse() {
138146
}
139147

140148
#[cfg(test)]
141-
macro_rules! test_file {
142-
($path:expr) => {{
143-
use super::*;
144-
145-
let file = PBXRootObject::try_from(PathBuf::from($path));
149+
macro_rules! test_demo_file {
150+
($name:expr) => {{
151+
let (root, name) = (env!("CARGO_MANIFEST_DIR"), stringify!($name));
152+
let path = format!("{root}/tests/samples/{name}.pbxproj");
153+
let file = crate::pbxproj::PBXRootObject::try_from(std::path::PathBuf::from(path));
146154
if file.is_err() {
147155
println!("Error: {:#?}", file.as_ref().unwrap_err())
148156
}
149157
assert!(file.is_ok());
150158
file.unwrap()
151159
}};
152160
}
161+
#[cfg(test)]
162+
pub(crate) use test_demo_file;
153163

154164
#[cfg(test)]
155165
mod create_tests {
156166
macro_rules! test_samples {
157167
($($name:ident),*) => {
158168
$(#[test]
159169
fn $name() {
160-
let (root, name) = (env!("CARGO_MANIFEST_DIR"), stringify!($name));
161-
test_file!(format!("{root}/tests/samples/{name}.pbxproj"));
170+
test_demo_file!($name);
162171
})*
163172
};
164173
}

0 commit comments

Comments
 (0)