Skip to content

Commit 0253c72

Browse files
committed
Don't prune features used by ext.rs
1 parent a37ea0e commit 0253c72

3 files changed

Lines changed: 107 additions & 3 deletions

File tree

cli/src/manifest.rs

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ pub struct Manifest {
1313
pub version: String,
1414
pub paths: BTreeMap<String, String>,
1515
pub dependencies: BTreeMap<String, Vec<String>>,
16+
#[serde(skip)]
17+
pub ext_wrappers: BTreeMap<String, Vec<String>>,
1618
}
1719

1820
const SCHEMA_VERSION: u32 = 1;
1921

2022
impl Manifest {
2123
pub fn load(path: &Path) -> Result<Self> {
2224
let raw = std::fs::read_to_string(path).with_context(|| format!("reading manifest at {}", path.display()))?;
23-
let m: Manifest = serde_json::from_str(&raw).with_context(|| format!("parsing manifest at {}", path.display()))?;
25+
let mut m: Manifest = serde_json::from_str(&raw).with_context(|| format!("parsing manifest at {}", path.display()))?;
2426

2527
if m.schema_version != SCHEMA_VERSION {
2628
return Err(anyhow!(
@@ -31,6 +33,10 @@ impl Manifest {
3133
));
3234
}
3335

36+
if let Some(bindings_root) = path.parent() {
37+
m.ext_wrappers = load_ext_wrappers(bindings_root).unwrap_or_default();
38+
}
39+
3440
Ok(m)
3541
}
3642

@@ -63,3 +69,81 @@ impl Manifest {
6369
out
6470
}
6571
}
72+
73+
fn load_ext_wrappers(bindings_root: &Path) -> Option<BTreeMap<String, Vec<String>>> {
74+
let ext_path = bindings_root.join("src").join("ext.rs");
75+
let text = std::fs::read_to_string(&ext_path).ok()?;
76+
let file = syn::parse_file(&text).ok()?;
77+
78+
let mut out: BTreeMap<String, Vec<String>> = BTreeMap::new();
79+
80+
for item in &file.items {
81+
let syn::Item::Mod(m) = item else { continue };
82+
let features = extract_cfg_features(&m.attrs);
83+
if features.is_empty() {
84+
continue;
85+
}
86+
87+
let Some((_, inner_items)) = m.content.as_ref() else { continue };
88+
89+
for inner in inner_items {
90+
let (name, is_pub) = match inner {
91+
syn::Item::Struct(s) => (s.ident.to_string(), is_public(&s.vis)),
92+
syn::Item::Trait(t) => (t.ident.to_string(), is_public(&t.vis)),
93+
syn::Item::Fn(f) => (f.sig.ident.to_string(), is_public(&f.vis)),
94+
_ => continue,
95+
};
96+
97+
if !is_pub {
98+
continue;
99+
}
100+
101+
out.insert(name, features.clone());
102+
}
103+
}
104+
105+
Some(out)
106+
}
107+
108+
fn is_public(vis: &syn::Visibility) -> bool {
109+
matches!(vis, syn::Visibility::Public(_))
110+
}
111+
112+
fn extract_cfg_features(attrs: &[syn::Attribute]) -> Vec<String> {
113+
for attr in attrs {
114+
if !attr.path().is_ident("cfg") {
115+
continue;
116+
}
117+
if let Ok(meta) = attr.parse_args::<syn::Meta>() {
118+
return collect_features(&meta);
119+
}
120+
}
121+
Vec::new()
122+
}
123+
124+
fn collect_features(meta: &syn::Meta) -> Vec<String> {
125+
match meta {
126+
syn::Meta::NameValue(nv) if nv.path.is_ident("feature") => {
127+
if let syn::Expr::Lit(syn::ExprLit {
128+
lit: syn::Lit::Str(s),
129+
..
130+
}) = &nv.value
131+
{
132+
vec![s.value()]
133+
} else {
134+
Vec::new()
135+
}
136+
}
137+
syn::Meta::List(list) if list.path.is_ident("all") => {
138+
let parsed: syn::punctuated::Punctuated<syn::Meta, syn::Token![,]> = list
139+
.parse_args_with(syn::punctuated::Punctuated::parse_terminated)
140+
.unwrap_or_default();
141+
let mut out = Vec::new();
142+
for inner in parsed {
143+
out.extend(collect_features(&inner));
144+
}
145+
out
146+
}
147+
_ => Vec::new(),
148+
}
149+
}

cli/src/scan.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,20 @@ pub fn collect_paths(
4646
}
4747

4848
pub fn paths_to_features(paths: &BTreeSet<String>, manifest: &Manifest) -> BTreeSet<String> {
49-
paths.iter().filter_map(|p| manifest.paths.get(p)).cloned().collect()
49+
let mut out: BTreeSet<String> = paths
50+
.iter()
51+
.filter_map(|p| manifest.paths.get(p))
52+
.cloned()
53+
.collect();
54+
55+
for p in paths {
56+
let leaf = p.rsplit("::").next().unwrap_or(p);
57+
if let Some(feats) = manifest.ext_wrappers.get(leaf) {
58+
out.extend(feats.iter().cloned());
59+
}
60+
}
61+
62+
out
5063
}
5164

5265
struct PathVisitor<'a> {
@@ -102,6 +115,13 @@ impl<'a> PathVisitor<'a> {
102115
return;
103116
}
104117

118+
if let Some(leaf) = segments.get(n - 1) {
119+
if self.manifest.ext_wrappers.contains_key(leaf) {
120+
self.out.insert(candidate);
121+
return;
122+
}
123+
}
124+
105125
for rewritten in rewrite_synthetic_trait(&segments[..n]) {
106126
if self.manifest.paths.contains_key(&rewritten) {
107127
self.out.insert(rewritten);

vscode/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "engage-vscode",
33
"displayName": "engage",
44
"description": "Manage engage-il2cpp Cargo features from VS Code",
5-
"version": "0.2.1",
5+
"version": "0.2.2",
66
"publisher": "DivineDragonFanClub",
77
"repository": {
88
"type": "git",

0 commit comments

Comments
 (0)