Skip to content

Commit

Permalink
cxx-qt-gen: build qualified mappings for QObject inline
Browse files Browse the repository at this point in the history
Rather than building the qualified mappings of the qobject
after already parsing them, do this inline. And build a
helper method to build a Path from two idents without parsing.

Related to #577
  • Loading branch information
ahayzen-kdab authored and Be-ing committed Jul 26, 2023
1 parent 9cbc1ea commit d22007d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
18 changes: 13 additions & 5 deletions crates/cxx-qt-gen/src/parser/cxxqtdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use crate::syntax::attribute::attribute_find_path;
use crate::syntax::foreignmod::{foreign_mod_to_foreign_item_types, ForeignTypeIdentAlias};
use crate::syntax::path::path_from_idents;
use crate::syntax::safety::Safety;
use crate::{
parser::{inherit::ParsedInheritedMethod, qobject::ParsedQObject, signals::ParsedSignal},
Expand All @@ -13,8 +14,8 @@ use crate::{
use quote::format_ident;
use std::collections::BTreeMap;
use syn::{
parse_quote, spanned::Spanned, Attribute, Error, ForeignItem, Ident, Item, ItemForeignMod,
ItemImpl, Path, Result, Type, TypePath,
spanned::Spanned, Attribute, Error, ForeignItem, Ident, Item, ItemForeignMod, ItemImpl, Path,
Result, Type, TypePath,
};

use super::method::ParsedMethod;
Expand Down Expand Up @@ -101,6 +102,12 @@ impl ParsedCxxQtData {
qobject.namespace = self.namespace.clone();
}

// Add the QObject type to the qualified mappings
self.qualified_mappings.insert(
foreign_alias.ident_left.clone(),
path_from_idents(&self.module_ident, &foreign_alias.ident_left),
);

// Note that we assume a compiler error will occur later
// if you had two structs with the same name
self.qobjects
Expand Down Expand Up @@ -191,9 +198,10 @@ impl ParsedCxxQtData {
} else {
ident.clone()
};
let module_ident = &self.module_ident;
self.qualified_mappings
.insert(ident.clone(), parse_quote! { #module_ident::#rust_ident });
self.qualified_mappings.insert(
ident.clone(),
path_from_idents(&self.module_ident, &rust_ident),
);

Ok(())
}
Expand Down
11 changes: 1 addition & 10 deletions crates/cxx-qt-gen/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ pub mod signals;

use crate::syntax::attribute::{attribute_find_path, attribute_tokens_to_map, AttributeDefault};
use cxxqtdata::ParsedCxxQtData;
use syn::{
spanned::Spanned, token::Brace, Error, Ident, ItemMod, LitStr, Path, PathSegment, Result,
};
use syn::{spanned::Spanned, token::Brace, Error, Ident, ItemMod, LitStr, Result};

/// A struct representing a module block with CXX-Qt relevant [syn::Item]'s
/// parsed into ParsedCxxQtData, to be used later to generate Rust & C++ code.
Expand Down Expand Up @@ -82,13 +80,6 @@ impl Parser {
others.push(other);
}
}

// Add all the QObject types to the qualified mappings
for ident in cxx_qt_data.qobjects.keys() {
let mut path = Path::from(module.ident.clone());
path.segments.push(PathSegment::from(ident.clone()));
cxx_qt_data.qualified_mappings.insert(ident.clone(), path);
}
}

// Create a new module using only items that are not CXX-Qt items
Expand Down
21 changes: 20 additions & 1 deletion crates/cxx-qt-gen/src/syntax/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: MIT OR Apache-2.0

use syn::Path;
use syn::{Ident, Path, PathSegment};

/// Returns whether the [syn::Path] matches a given string slice
pub fn path_compare_str(path: &Path, string: &[&str]) -> bool {
Expand All @@ -20,8 +20,20 @@ pub fn path_compare_str(path: &Path, string: &[&str]) -> bool {
== 0
}

/// For a given ident and base ident build a qualified path
///
/// Eg `module` and `T` build `module::T`
pub fn path_from_idents(base: &Ident, ident: &Ident) -> Path {
let mut qualified_path = Path::from(base.clone());
qualified_path
.segments
.push(PathSegment::from(ident.clone()));
qualified_path
}

#[cfg(test)]
mod tests {
use quote::format_ident;
use syn::parse_quote;

use super::*;
Expand All @@ -34,4 +46,11 @@ mod tests {
assert!(!path_compare_str(&path, &["a", "c", "b"]));
assert!(!path_compare_str(&path, &["a", "b", "c", "d"]));
}

#[test]
fn test_path_from_idents() {
let path = path_from_idents(&format_ident!("ffi"), &format_ident!("T"));
let expected_path: Path = parse_quote! { ffi::T };
assert_eq!(path, expected_path);
}
}

0 comments on commit d22007d

Please sign in to comment.