From d22007defb7110c88d0c064eff06e2eb9fadaca8 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Wed, 26 Jul 2023 16:48:13 +0100 Subject: [PATCH] cxx-qt-gen: build qualified mappings for QObject inline 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 --- crates/cxx-qt-gen/src/parser/cxxqtdata.rs | 18 +++++++++++++----- crates/cxx-qt-gen/src/parser/mod.rs | 11 +---------- crates/cxx-qt-gen/src/syntax/path.rs | 21 ++++++++++++++++++++- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index c72bb1019..df379dfe2 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -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}, @@ -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; @@ -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 @@ -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(()) } diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 7a140796a..4275f0dc8 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -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. @@ -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 diff --git a/crates/cxx-qt-gen/src/syntax/path.rs b/crates/cxx-qt-gen/src/syntax/path.rs index 5cb2ebbcf..9e9529fa1 100644 --- a/crates/cxx-qt-gen/src/syntax/path.rs +++ b/crates/cxx-qt-gen/src/syntax/path.rs @@ -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 { @@ -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::*; @@ -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); + } }