Skip to content

Commit

Permalink
cxx-qt-gen: move populate mappings to the mappings module
Browse files Browse the repository at this point in the history
  • Loading branch information
ahayzen-kdab committed Jul 31, 2023
1 parent cbf9ddb commit 6d8f8a5
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 57 deletions.
68 changes: 12 additions & 56 deletions crates/cxx-qt-gen/src/parser/cxxqtdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ use crate::{
},
syntax::expr::expr_to_string,
};
use quote::format_ident;
use std::collections::BTreeMap;
use syn::{
spanned::Spanned, Attribute, Error, ForeignItem, Ident, Item, ItemForeignMod, ItemImpl, Result,
Type, TypePath,
spanned::Spanned, Error, ForeignItem, Ident, Item, ItemEnum, ItemForeignMod, ItemImpl,
ItemStruct, Result, Type, TypePath,
};

pub struct ParsedCxxQtData {
Expand Down Expand Up @@ -119,11 +118,10 @@ impl ParsedCxxQtData {

// Consider if shared types have mappings
match item {
Item::Enum(item) => {
self.populate_mappings(&item.ident, &item.attrs, &bridge_namespace)?;
}
Item::Struct(item) => {
self.populate_mappings(&item.ident, &item.attrs, &bridge_namespace)?;
Item::Enum(ItemEnum { attrs, ident, .. })
| Item::Struct(ItemStruct { attrs, ident, .. }) => {
self.cxx_mappings
.populate(ident, attrs, &bridge_namespace, &self.module_ident)?;
}
_others => {}
}
Expand All @@ -150,59 +148,17 @@ impl ParsedCxxQtData {

// Read each of the types in the mod (type A;)
for foreign_type in foreign_mod_to_foreign_item_types(foreign_mod)? {
self.populate_mappings(&foreign_type.ident, &foreign_type.attrs, &block_namespace)?;
self.cxx_mappings.populate(
&foreign_type.ident,
&foreign_type.attrs,
&block_namespace,
&self.module_ident,
)?;
}

Ok(())
}

/// Helper which adds cxx_name, rust_name, and namespace mappings from the ident, attrs, parent namespace, and module ident
fn populate_mappings(
&mut self,
ident: &Ident,
attrs: &[Attribute],
parent_namespace: &str,
) -> Result<()> {
// Retrieve the namespace for the type itself if there is one
let namespace = if let Some(index) = attribute_find_path(attrs, &["namespace"]) {
expr_to_string(&attrs[index].meta.require_name_value()?.value)?
} else {
parent_namespace.to_string()
};

// There is a cxx_name attribute
if let Some(index) = attribute_find_path(attrs, &["cxx_name"]) {
self.cxx_mappings.cxx_names.insert(
ident.to_string(),
expr_to_string(&attrs[index].meta.require_name_value()?.value)?,
);
}

// There is a namespace
if !namespace.is_empty() {
self.cxx_mappings
.namespaces
.insert(ident.to_string(), namespace);
}

// Add type to qualified mappings
let rust_ident = if let Some(index) = attribute_find_path(attrs, &["rust_name"]) {
format_ident!(
"{}",
expr_to_string(&attrs[index].meta.require_name_value()?.value)?,
span = attrs[index].span()
)
} else {
ident.clone()
};
self.cxx_mappings.qualified.insert(
ident.clone(),
path_from_idents(&self.module_ident, &rust_ident),
);

Ok(())
}

/// Determine if the given [syn::Item] is a CXX-Qt related item
/// If it is then add the [syn::Item] into qobjects BTreeMap
/// Otherwise return the [syn::Item] to pass through to CXX
Expand Down
52 changes: 51 additions & 1 deletion crates/cxx-qt-gen/src/parser/mappings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

use std::collections::BTreeMap;

use syn::{Ident, Path};
use quote::format_ident;
use syn::{spanned::Spanned, Attribute, Ident, Path, Result};

use crate::syntax::{attribute::attribute_find_path, expr::expr_to_string, path::path_from_idents};

#[derive(Default)]
pub struct ParsedCxxMappings {
Expand All @@ -18,6 +21,8 @@ pub struct ParsedCxxMappings {
/// This is used in the C++ generation to map the Rust type name to the C++ name
pub namespaces: BTreeMap<String, String>,
/// Mappings for CXX types when used outside the bridge
///
/// This is used in the Rust generation to map the bridge type A to ffi::B
pub qualified: BTreeMap<Ident, Path>,
}

Expand All @@ -37,4 +42,49 @@ impl ParsedCxxMappings {
cxx_name
}
}

/// Helper which builds mappings from namespace, cxx_name, and rust_name attributes
pub fn populate(
&mut self,
ident: &Ident,
attrs: &[Attribute],
parent_namespace: &str,
module_ident: &Ident,
) -> Result<()> {
// Find if there is a namespace (for C++ generation)
let namespace = if let Some(index) = attribute_find_path(attrs, &["namespace"]) {
expr_to_string(&attrs[index].meta.require_name_value()?.value)?
} else {
parent_namespace.to_string()
};

if !namespace.is_empty() {
self.namespaces.insert(ident.to_string(), namespace);
}

// Find if there is a cxx_name mapping (for C++ generation)
if let Some(index) = attribute_find_path(attrs, &["cxx_name"]) {
self.cxx_names.insert(
ident.to_string(),
expr_to_string(&attrs[index].meta.require_name_value()?.value)?,
);
}

// Find if there is a rust_name mapping
let rust_ident = if let Some(index) = attribute_find_path(attrs, &["rust_name"]) {
format_ident!(
"{}",
expr_to_string(&attrs[index].meta.require_name_value()?.value)?,
span = attrs[index].span()
)
} else {
ident.clone()
};

// Add the rust_ident to qualified mappings (for Rust generation using ffi::T)
self.qualified
.insert(ident.clone(), path_from_idents(module_ident, &rust_ident));

Ok(())
}
}

0 comments on commit 6d8f8a5

Please sign in to comment.