Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added target_os cfg feature to header translator #433

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Made use of cfg target in library imports
  • Loading branch information
simlay committed Apr 4, 2023
commit 39ce7d59c9884b69a4b7822c2449fab2bd9f46a2
15 changes: 8 additions & 7 deletions crates/header-translator/src/availability.rs
Original file line number Diff line number Diff line change
@@ -14,21 +14,22 @@ pub struct Unavailable {
pub(crate) maccatalyst: bool,
pub(crate) watchos: bool,
pub(crate) tvos: bool,
pub(crate) library_unavailablility: Box<Unavailable>,
pub(crate) library_unavailablility: Option<Box<Unavailable>>,
}
impl fmt::Display for Unavailable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut unavailable_oses = Vec::new();
if self.ios && !self.library_unavailablility.ios {
if self.ios && !self.library_unavailablility.as_ref().map(|u| u.ios).unwrap_or_else(|| false)
{
unavailable_oses.push("target_os = \"ios\"");
}
if self.macos && !self.library_unavailablility.macos {
if self.macos && !self.library_unavailablility.as_ref().map(|u| u.macos).unwrap_or_else(|| false) {
unavailable_oses.push("target_os = \"macos\"");
}
if self.tvos && !self.library_unavailablility.tvos {
if self.tvos && !self.library_unavailablility.as_ref().map(|u| u.tvos).unwrap_or_else(|| false) {
unavailable_oses.push("target_os = \"tvos\"");
}
if self.watchos && !self.library_unavailablility.watchos {
if self.watchos && !self.library_unavailablility.as_ref().map(|u| u.watchos).unwrap_or_else(|| false) {
unavailable_oses.push("target_os = \"watchos\"");
}

@@ -53,7 +54,7 @@ struct Versions {

#[derive(Debug, Clone, PartialEq)]
pub struct Availability {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[deprecated] now also appears on impl ClassType, which is incorrect.

So perhaps we should split out the Unavailable from Availability (and maybe rename it to PlatformCfg)? Since that part is always going to be a cfg-gate, which has interactions with higher-level cfg-gates (and must propagate to imports like generated/[Framework]/mod.rs), while introduced and deprecated will always only need to apply to the statement/method/field they're associated with.

Maybe it would even make sense to add PlatformCfg as a field of ItemIdentifier? Since these two are access so often together.

unavailable: Unavailable,
pub(crate) unavailable: Unavailable,
introduced: Versions,
deprecated: Versions,
message: Option<String>,
@@ -67,7 +68,7 @@ impl Availability {
.expect("platform availability");

let mut unavailable = Unavailable::default();
unavailable.library_unavailablility = Box::new(library_unavailablility.clone());
unavailable.library_unavailablility = Some(Box::new(library_unavailablility.clone()));
let mut introduced = Versions::default();
let mut deprecated = Versions::default();
let mut message = None;
59 changes: 28 additions & 31 deletions crates/header-translator/src/library.rs
Original file line number Diff line number Diff line change
@@ -63,39 +63,36 @@ impl fmt::Display for Library {
// NOTE: some SDK files have '+' in the file name
let name = name.replace('+', "_");
for stmt in &file.stmts {
let mut iter = stmt.declared_types();
if let Some(item) = iter.next() {
// Use a set to deduplicate features, and to have them in
// a consistent order
let mut features = BTreeSet::new();
stmt.visit_required_types(|item| {
if let Some(feature) = item.feature() {
features.insert(format!("feature = \"{feature}\""));
}
});
match features.len() {
0 => {}
1 => {
writeln!(f, "#[cfg({})]", features.first().unwrap())?;
}
_ => {
writeln!(
f,
"#[cfg(all({}))]",
features
.iter()
.map(|s| &**s)
.collect::<Vec<&str>>()
.join(",")
)?;
}
// Use a set to deduplicate features, and to have them in
// a consistent order
let mut features = BTreeSet::new();
stmt.visit_required_types(|item| {
if let Some(feature) = item.feature() {
features.insert(format!("feature = \"{feature}\""));
}

writeln!(f, "pub use self::__{name}::{{{item}")?;
for item in iter {
writeln!(f, ", {item}")?;
});
match features.len() {
0 => {}
1 => {
writeln!(f, "#[cfg({})]", features.first().unwrap())?;
}
_ => {
writeln!(
f,
"#[cfg(all({}))]",
features
.iter()
.map(|s| &**s)
.collect::<Vec<&str>>()
.join(",")
)?;
}
writeln!(f, "}};")?;
}
let mut iter = stmt.declared_types();

for (item, unavailability) in iter {
writeln!(f, "{unavailability}")?;
writeln!(f, "pub use self::__{name}::{{{item}}};")?;
}
}
}
20 changes: 10 additions & 10 deletions crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
@@ -976,24 +976,24 @@ impl Stmt {
}
}

pub(crate) fn declared_types(&self) -> impl Iterator<Item = &str> {
pub(crate) fn declared_types(&self) -> impl Iterator<Item = (&str, &Unavailable)> {
match self {
Stmt::ClassDecl { id, .. } => Some(&*id.name),
Stmt::ClassDecl { id, availability, .. } => Some((&*id.name, &availability.unavailable)),
Stmt::Methods { .. } => None,
Stmt::ProtocolDecl { id, .. } => Some(&*id.name),
Stmt::ProtocolDecl { id, availability, .. } => Some((&*id.name, &availability.unavailable)),
Stmt::ProtocolImpl { .. } => None,
Stmt::StructDecl { id, .. } => Some(&*id.name),
Stmt::EnumDecl { id, .. } => id.name.as_deref(),
Stmt::VarDecl { id, .. } => Some(&*id.name),
Stmt::FnDecl { id, body, .. } if body.is_none() => Some(&*id.name),
Stmt::StructDecl { id, availability, .. } => Some((&*id.name, &availability.unavailable)),
Stmt::EnumDecl { id, availability, .. } => id.name.as_deref().map(|name| (name, &availability.unavailable)),
Stmt::VarDecl { id, availability, .. } => Some((&*id.name, &availability.unavailable)),
Stmt::FnDecl { id, body, availability, .. } if body.is_none() => Some((&*id.name, &availability.unavailable)),
// TODO
Stmt::FnDecl { .. } => None,
Stmt::AliasDecl { id, .. } => Some(&*id.name),
Stmt::AliasDecl { id, availability, .. } => Some((&*id.name, &availability.unavailable)),
}
.into_iter()
.chain({
if let Stmt::EnumDecl { variants, .. } = self {
variants.iter().map(|(name, _, _)| &**name).collect()
if let Stmt::EnumDecl { variants, availability, .. } = self {
variants.iter().map(|(name, _, _)| (&**name, &availability.unavailable)).collect()
} else {
vec![]
}