Skip to content

Commit fe79438

Browse files
committed
Make config.rs independent of the rest of header-translator
1 parent 39bf29b commit fe79438

10 files changed

Lines changed: 237 additions & 257 deletions

File tree

‎crates/header-translator/src/config.rs‎

Lines changed: 18 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@ use std::str::FromStr;
88
use std::sync::OnceLock;
99
use std::{fmt, ptr};
1010

11-
use clang::{Entity, EntityKind};
1211
use heck::ToTrainCase;
1312
use semver::Version;
1413
use serde::{de, Deserialize, Deserializer};
1514

16-
use crate::name_translation::cf_no_ref;
17-
use crate::{ItemIdentifier, Location};
18-
1915
#[derive(Debug, Clone, PartialEq, Eq)]
2016
pub struct Config {
2117
pub libraries: BTreeMap<String, LibraryConfig>,
@@ -95,89 +91,16 @@ impl Config {
9591
self.libraries.get(library_name)
9692
}
9793

98-
/// Look up the library config.
99-
///
100-
/// This only needs the library name, but it takes ItemIdentifier or
101-
/// Location for better error reporting.
102-
pub fn library(&self, location: impl AsRef<Location> + fmt::Debug) -> &LibraryConfig {
103-
self.try_library(location.as_ref().library_name())
104-
.unwrap_or_else(|| {
105-
error!("tried to get library config from {location:?}");
106-
self.libraries
107-
.get("__builtin__")
108-
.expect("could not find builtin library")
109-
})
110-
}
111-
112-
pub fn library_from_crate(&self, krate: &str) -> &LibraryConfig {
113-
self.try_library_from_crate(krate).unwrap_or_else(|| {
114-
error!("tried to get library config from krate {krate:?}");
115-
self.libraries
116-
.get("__builtin__")
117-
.expect("could not find builtin library")
118-
})
119-
}
120-
12194
pub fn try_library_from_crate(&self, krate: &str) -> Option<&LibraryConfig> {
12295
self.libraries.values().find(|lib| lib.krate == krate)
12396
}
12497

125-
pub fn replace_typedef_name(&self, id: ItemIdentifier, is_cf: bool) -> ItemIdentifier {
126-
let library_config = self.library(&id);
127-
id.map_name(|name| {
128-
library_config
129-
.typedef_data
130-
.get(&name)
131-
.and_then(|data| data.renamed.clone())
132-
.unwrap_or_else(|| {
133-
// If a typedef's underlying type is itself a "CF pointer"
134-
// typedef, the "alias" typedef will be imported as a
135-
// regular typealias, with the suffix "Ref" still dropped
136-
// from its name (if present).
137-
//
138-
// <https://github.com/swiftlang/swift/blob/swift-6.0.3-RELEASE/docs/CToSwiftNameTranslation.md#cf-types>
139-
//
140-
// NOTE: There's an extra clause that we don't support:
141-
// > unless doing so would conflict with another
142-
// > declaration in the same module as the typedef.
143-
//
144-
// We'll have to manually keep the name of those in
145-
// translation-config.toml.
146-
if is_cf {
147-
cf_no_ref(&name).to_string()
148-
} else {
149-
name
150-
}
151-
})
152-
})
153-
}
154-
15598
pub fn to_parse(&self) -> impl Iterator<Item = (&str, &LibraryConfig)> + Clone {
15699
self.libraries
157100
.iter()
158101
.filter(|(_, data)| !data.skipped)
159102
.map(|(name, data)| (&**name, data))
160103
}
161-
162-
pub fn module_configs<'l>(
163-
&'l self,
164-
location: &'l Location,
165-
) -> impl Iterator<Item = &'l ModuleConfig> + 'l {
166-
self.try_library(location.library_name())
167-
.map(|library| {
168-
let mut current = &library.module;
169-
location.modules().map_while(move |component| {
170-
if let Some(module_config) = current.get(component) {
171-
current = &module_config.module;
172-
Some(module_config)
173-
} else {
174-
None
175-
}
176-
})
177-
})
178-
.into_iter()
179-
.flatten()
180-
}
181104
}
182105

183106
fn get_version<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Version>, D::Error> {
@@ -213,13 +136,7 @@ fn get_version<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Option<Vers
213136
#[derive(Deserialize, Debug, Clone, PartialEq, Eq)]
214137
#[serde(deny_unknown_fields)]
215138
pub struct ExternalData {
216-
pub(crate) module: Location,
217-
}
218-
219-
impl ExternalData {
220-
pub(crate) fn into_id(self, name: String) -> ItemIdentifier {
221-
ItemIdentifier::from_raw(name, self.module)
222-
}
139+
pub(crate) module: String,
223140
}
224141

225142
#[derive(Deserialize, Debug, Default, Clone, PartialEq, Eq)]
@@ -535,57 +452,6 @@ impl LibraryConfig {
535452
assert_eq!(data.opaque, Default::default());
536453
}
537454
}
538-
539-
pub(crate) fn get(&self, entity: &Entity<'_>) -> &StmtData {
540-
let name = if entity.is_anonymous() {
541-
// union (unnamed at /Applications/Xcode.app/...)
542-
// union (anonymous at /Applications/Xcode.app/...)
543-
// enum (unnamed at /Applications/Xcode.app/...)
544-
// struct (unnamed at /Applications/Xcode.app/...)
545-
//
546-
// Anonymous enums don't have a name that we can use to look up
547-
// a config. So we use the special "__anonymous__" instead.
548-
"__anonymous__".to_string()
549-
} else {
550-
if let Some(name) = entity.get_name() {
551-
name
552-
} else {
553-
return StmtData::empty();
554-
}
555-
};
556-
557-
let data = match entity.get_kind() {
558-
EntityKind::ObjCInterfaceDecl | EntityKind::ObjCClassRef => self.class_data.get(&name),
559-
EntityKind::ObjCCategoryDecl => None, // TODO
560-
EntityKind::ObjCProtocolDecl | EntityKind::ObjCProtocolRef => {
561-
self.protocol_data.get(&name)
562-
}
563-
EntityKind::TypedefDecl => self.typedef_data.get(&name),
564-
EntityKind::StructDecl => self.struct_data.get(&name),
565-
EntityKind::UnionDecl => self.union_data.get(&name),
566-
EntityKind::EnumDecl => self.enum_data.get(&name),
567-
EntityKind::EnumConstantDecl => self.const_data.get(&name),
568-
EntityKind::VarDecl => self.statics.get(&name),
569-
EntityKind::FunctionDecl => self.fns.get(&name),
570-
EntityKind::FieldDecl => None, // TODO
571-
// TODO: Add #[doc(alias = ...)] on methods?
572-
EntityKind::ObjCClassMethodDecl
573-
| EntityKind::ObjCInstanceMethodDecl
574-
| EntityKind::ObjCPropertyDecl => None,
575-
EntityKind::MacroDefinition | EntityKind::MacroExpansion => None,
576-
EntityKind::UnexposedDecl => None,
577-
EntityKind::TemplateTypeParameter => None,
578-
kind => {
579-
error!(
580-
?kind,
581-
"tried to look up ItemIdentifier from unknown entity kind"
582-
);
583-
None
584-
}
585-
};
586-
587-
data.unwrap_or_else(|| StmtData::empty())
588-
}
589455
}
590456

591457
#[derive(Deserialize, Debug, Default, Clone, PartialEq, Eq)]
@@ -634,7 +500,7 @@ pub struct StmtData {
634500
/// They are correctness-checked in `global_analysis.rs` though.
635501
#[serde(default)]
636502
#[serde(rename = "bridged-to")]
637-
pub bridged_to: Option<ItemIdentifier>,
503+
pub bridged_to: Option<String>,
638504

639505
// Protocol only.
640506
#[serde(default)]
@@ -650,7 +516,7 @@ pub struct StmtData {
650516
#[serde(default)]
651517
pub no_implementor: bool,
652518
#[serde(default)]
653-
pub implementor: Option<ItemIdentifier>,
519+
pub implementor: Option<String>,
654520
#[serde(default)]
655521
#[serde(deserialize_with = "deserialize_argument_overrides")]
656522
pub arguments: HashMap<usize, TypeOverride>,
@@ -713,15 +579,6 @@ pub enum Nullability {
713579
NonNull,
714580
}
715581

716-
impl From<Nullability> for clang::Nullability {
717-
fn from(nullability: Nullability) -> Self {
718-
match nullability {
719-
Nullability::Nullable => clang::Nullability::Nullable,
720-
Nullability::NonNull => clang::Nullability::NonNull,
721-
}
722-
}
723-
}
724-
725582
/// The bounds of a raw pointer.
726583
///
727584
/// Modelled after <https://clang.llvm.org/docs/BoundsSafety.html>.
@@ -945,9 +802,9 @@ pub enum Counterpart {
945802
#[default]
946803
NoCounterpart,
947804
#[serde(rename = "immutable-superclass")]
948-
ImmutableSuperclass(ItemIdentifier),
805+
ImmutableSuperclass(String),
949806
#[serde(rename = "mutable-subclass")]
950-
MutableSubclass(ItemIdentifier),
807+
MutableSubclass(String),
951808
}
952809

953810
fn deserialize_argument_overrides<'de, D>(
@@ -981,7 +838,7 @@ where
981838

982839
#[derive(Debug, Clone, PartialEq, Eq)]
983840
pub struct ItemGeneric {
984-
pub id: ItemIdentifier,
841+
pub id: String,
985842
pub generics: Vec<ItemGeneric>,
986843
}
987844

@@ -1016,15 +873,15 @@ impl FromStr for ItemGeneric {
1016873
Err(std::io::Error::other("unexpected after >"))?;
1017874
}
1018875
Ok(Self {
1019-
id: ItemIdentifier::from_str(id)?,
876+
id: id.to_string(),
1020877
generics: split_top_level_commas(generics)
1021878
.into_iter()
1022879
.map(|g| g.parse::<ItemGeneric>())
1023880
.collect::<Result<Vec<_>, _>>()?,
1024881
})
1025882
} else {
1026883
Ok(Self {
1027-
id: ItemIdentifier::from_str(s)?,
884+
id: s.to_string(),
1028885
generics: vec![],
1029886
})
1030887
}
@@ -1066,22 +923,22 @@ mod tests {
1066923
assert_eq!(
1067924
ItemGeneric::from_str("Foo.Bar").unwrap(),
1068925
ItemGeneric {
1069-
id: ItemIdentifier::from_str("Foo.Bar").unwrap(),
926+
id: "Foo.Bar".to_string(),
1070927
generics: vec![],
1071928
}
1072929
);
1073930

1074931
assert_eq!(
1075932
ItemGeneric::from_str("Foo.Bar<X.Y.Z, A.B.C>").unwrap(),
1076933
ItemGeneric {
1077-
id: ItemIdentifier::from_str("Foo.Bar").unwrap(),
934+
id: "Foo.Bar".to_string(),
1078935
generics: vec![
1079936
ItemGeneric {
1080-
id: ItemIdentifier::from_str("X.Y.Z").unwrap(),
937+
id: "X.Y.Z".to_string(),
1081938
generics: vec![],
1082939
},
1083940
ItemGeneric {
1084-
id: ItemIdentifier::from_str("A.B.C").unwrap(),
941+
id: "A.B.C".to_string(),
1085942
generics: vec![],
1086943
},
1087944
],
@@ -1094,27 +951,27 @@ mod tests {
1094951
)
1095952
.unwrap(),
1096953
ItemGeneric {
1097-
id: ItemIdentifier::from_str("Foo.Bar").unwrap(),
954+
id: "Foo.Bar".to_string(),
1098955
generics: vec![
1099956
ItemGeneric {
1100-
id: ItemIdentifier::from_str("X.Y.Z").unwrap(),
957+
id: "X.Y.Z".to_string(),
1101958
generics: vec![],
1102959
},
1103960
ItemGeneric {
1104-
id: ItemIdentifier::from_str("Inner.Item").unwrap(),
961+
id: "Inner.Item".to_string(),
1105962
generics: vec![
1106963
ItemGeneric {
1107-
id: ItemIdentifier::from_str("With.Generic").unwrap(),
964+
id: "With.Generic".to_string(),
1108965
generics: vec![],
1109966
},
1110967
ItemGeneric {
1111-
id: ItemIdentifier::from_str("Second.Generic").unwrap(),
968+
id: "Second.Generic".to_string(),
1112969
generics: vec![],
1113970
}
1114971
],
1115972
},
1116973
ItemGeneric {
1117-
id: ItemIdentifier::from_str("A.B.C").unwrap(),
974+
id: "A.B.C".to_string(),
1118975
generics: vec![],
1119976
},
1120977
],

‎crates/header-translator/src/context.rs‎

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1+
use core::fmt;
12
use std::collections::HashMap;
23
use std::ops;
34

45
use clang::Entity;
56
use proc_macro2::TokenStream;
67

7-
use crate::config::Config;
8+
use crate::config::{Config, ModuleConfig};
89
use crate::expr::Expr;
910
use crate::unexposed_attr::{get_argument_tokens, parse_macro_arguments};
10-
use crate::ItemIdentifier;
11+
use crate::{ItemIdentifier, LibraryConfig, Location};
1112

1213
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1314
pub struct MacroLocation {
@@ -88,6 +89,26 @@ impl<'config> Context<'config> {
8889
current_library,
8990
}
9091
}
92+
93+
pub fn module_configs<'l>(
94+
&'l self,
95+
location: &'l Location,
96+
) -> impl Iterator<Item = &'l ModuleConfig> + 'l {
97+
self.try_library(location.library_name())
98+
.map(|library| {
99+
let mut current = &library.module;
100+
location.modules().map_while(move |component| {
101+
if let Some(module_config) = current.get(component) {
102+
current = &module_config.module;
103+
Some(module_config)
104+
} else {
105+
None
106+
}
107+
})
108+
})
109+
.into_iter()
110+
.flatten()
111+
}
91112
}
92113

93114
impl ops::Deref for Context<'_> {
@@ -97,3 +118,23 @@ impl ops::Deref for Context<'_> {
97118
self.config
98119
}
99120
}
121+
122+
pub trait LibraryFromLocation {
123+
/// Look up the library config.
124+
///
125+
/// This only needs the library name, but it takes ItemIdentifier or
126+
/// Location for better error reporting.
127+
fn library(&self, location: impl AsRef<Location> + fmt::Debug) -> &LibraryConfig;
128+
}
129+
130+
impl LibraryFromLocation for Config {
131+
fn library(&self, location: impl AsRef<Location> + fmt::Debug) -> &LibraryConfig {
132+
self.try_library(location.as_ref().library_name())
133+
.unwrap_or_else(|| {
134+
error!("tried to get library config from {location:?}");
135+
self.libraries
136+
.get("__builtin__")
137+
.expect("could not find builtin library")
138+
})
139+
}
140+
}

‎crates/header-translator/src/documentation.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use clang::documentation::{
66
};
77
use clang::Entity;
88

9+
use crate::context::LibraryFromLocation;
910
use crate::display_helper::FormatterFn;
11+
use crate::stmt::stmt_data;
1012
use crate::{Context, ItemIdentifier};
1113

1214
#[derive(Debug, Clone, PartialEq)]
@@ -42,7 +44,7 @@ impl Documentation {
4244
};
4345

4446
let library = context.library(ItemIdentifier::new_optional(entity, context));
45-
let alias = if let Some(renamed) = &library.get(entity).renamed {
47+
let alias = if let Some(renamed) = &stmt_data(library, entity).renamed {
4648
let name = entity.get_name().expect("renamed entity must have name");
4749
if *renamed != name {
4850
Some(name)

0 commit comments

Comments
 (0)