Skip to content

Commit 3458fe1

Browse files
authored
wit-encoder: interface identifier and getter setter fixes (#1873)
* wit-encoder: add missing getters and setters for WorldNamedInterface * wit-encoder: fix getters * wit_encoder: fix interface identifiers * add test for import, exports, uses with and without version, and for the same and dep packages * test cleanup * test cleanup and add check for resolved-encoded output * fmt
1 parent 28ea1a0 commit 3458fe1

File tree

5 files changed

+302
-66
lines changed

5 files changed

+302
-66
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/wit-encoder/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@ wit-parser = { workspace = true, optional = true }
3333
id-arena = { workspace = true, optional = true }
3434

3535
[dev-dependencies]
36+
anyhow = { workspace = true }
3637
indoc = { workspace = true }

crates/wit-encoder/src/from_parser.rs

Lines changed: 97 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use id_arena::Id;
2-
31
use crate::{
4-
Enum, Flags, Interface, InterfaceItem, Package, PackageName, Params, Record, Resource,
2+
Enum, Flags, Ident, Interface, InterfaceItem, Package, PackageName, Params, Record, Resource,
53
ResourceFunc, Result_, Results, StandaloneFunc, Tuple, Type, TypeDef, TypeDefKind, Variant,
64
World, WorldItem,
75
};
6+
use id_arena::Id;
7+
use wit_parser::PackageId;
88

99
pub fn packages_from_parsed(resolve: &wit_parser::Resolve) -> Vec<Package> {
1010
let converter = Converter::new(resolve);
@@ -24,23 +24,24 @@ impl<'a> Converter<'a> {
2424
self.resolve
2525
.packages
2626
.iter()
27-
.map(|(_, p)| self.convert_package(p))
27+
.map(|(p_id, p)| self.convert_package(p_id, p))
2828
.collect()
2929
}
3030

31-
fn convert_package(&self, package: &wit_parser::Package) -> Package {
31+
fn convert_package(&self, package_id: PackageId, package: &wit_parser::Package) -> Package {
3232
let mut output = Package::new(self.convert_package_name(&package.name));
3333
for (_, id) in &package.interfaces {
3434
let interface = self.resolve.interfaces.get(*id).unwrap();
3535
output.interface(self.convert_interface(
36+
package_id,
3637
interface,
3738
None,
3839
wit_parser::TypeOwner::Interface(*id),
3940
));
4041
}
4142
for (_, id) in &package.worlds {
4243
let world = self.resolve.worlds.get(*id).unwrap();
43-
output.world(self.convert_world(world, wit_parser::TypeOwner::World(*id)));
44+
output.world(self.convert_world(package_id, world, wit_parser::TypeOwner::World(*id)));
4445
}
4546
output
4647
}
@@ -53,33 +54,30 @@ impl<'a> Converter<'a> {
5354
)
5455
}
5556

56-
fn convert_world(&self, world: &wit_parser::World, owner: wit_parser::TypeOwner) -> World {
57+
fn convert_world(
58+
&self,
59+
package_id: PackageId,
60+
world: &wit_parser::World,
61+
owner: wit_parser::TypeOwner,
62+
) -> World {
5763
let mut output = World::new(world.name.clone());
5864

5965
for (key, item) in &world.imports {
6066
match item {
6167
wit_parser::WorldItem::Interface { id, .. } => {
6268
let interface = self.resolve.interfaces.get(*id).unwrap();
63-
output.item(match &interface.name {
64-
Some(name) => {
65-
// standalone
66-
WorldItem::named_interface_import(name.clone())
67-
}
68-
None => {
69-
// inlined
70-
let name = match key {
71-
wit_parser::WorldKey::Name(name) => name.clone(),
72-
wit_parser::WorldKey::Interface(_) => {
73-
unreachable!("inlined interface must have a kye name")
74-
}
75-
};
76-
WorldItem::inline_interface_import(self.convert_interface(
77-
interface,
78-
Some(name),
79-
owner,
80-
))
81-
}
82-
});
69+
let ident = self.interface_ident(package_id, Some(key), interface);
70+
71+
if interface.name.is_some() {
72+
output.item(WorldItem::named_interface_import(ident))
73+
} else {
74+
output.item(WorldItem::inline_interface_import(self.convert_interface(
75+
package_id,
76+
interface,
77+
Some(ident),
78+
owner,
79+
)))
80+
}
8381
}
8482
wit_parser::WorldItem::Function(func) => {
8583
if let Some(func) = self.standalone_func_convert(func) {
@@ -95,26 +93,17 @@ impl<'a> Converter<'a> {
9593
match item {
9694
wit_parser::WorldItem::Interface { id, .. } => {
9795
let interface = self.resolve.interfaces.get(*id).unwrap();
98-
output.item(match &interface.name {
99-
Some(name) => {
100-
// standalone
101-
WorldItem::named_interface_export(name.clone())
102-
}
103-
None => {
104-
// inlined
105-
let name = match key {
106-
wit_parser::WorldKey::Name(name) => name.clone(),
107-
wit_parser::WorldKey::Interface(_) => {
108-
unreachable!("inlined interface must have a kye name")
109-
}
110-
};
111-
WorldItem::inline_interface_export(self.convert_interface(
112-
interface,
113-
Some(name),
114-
owner,
115-
))
116-
}
117-
});
96+
let ident = self.interface_ident(package_id, Some(key), interface);
97+
if interface.name.is_some() {
98+
output.item(WorldItem::named_interface_export(ident));
99+
} else {
100+
output.item(WorldItem::inline_interface_export(self.convert_interface(
101+
package_id,
102+
interface,
103+
Some(ident),
104+
owner,
105+
)));
106+
}
118107
}
119108
wit_parser::WorldItem::Function(func) => {
120109
if let Some(func) = self.standalone_func_convert(func) {
@@ -132,15 +121,17 @@ impl<'a> Converter<'a> {
132121

133122
fn convert_interface(
134123
&self,
124+
package_id: PackageId,
135125
interface: &wit_parser::Interface,
136-
inlined_name: Option<String>,
126+
inlined_name: Option<Ident>,
137127
owner: wit_parser::TypeOwner,
138128
) -> Interface {
139-
let mut output = Interface::new(interface.name.clone().unwrap_or_else(|| {
140-
inlined_name
141-
.clone()
142-
.expect("inlined interface must pass in inlined_name")
143-
}));
129+
let mut output =
130+
Interface::new(interface.name.clone().map(Ident::new).unwrap_or_else(|| {
131+
inlined_name
132+
.clone()
133+
.expect("inlined interface must pass in inlined_name")
134+
}));
144135

145136
for (_, func) in &interface.functions {
146137
if let Some(func) = self.standalone_func_convert(func) {
@@ -166,24 +157,21 @@ impl<'a> Converter<'a> {
166157
output.item(InterfaceItem::TypeDef(type_def));
167158
}
168159
} else {
169-
let interface_name = match underlying_type_def.owner {
170-
wit_parser::TypeOwner::Interface(id) => self
171-
.resolve
172-
.interfaces
173-
.get(id)
174-
.unwrap()
175-
.name
176-
.clone()
177-
.expect("can't use type from inline interface"),
160+
let interface_ident = match underlying_type_def.owner {
161+
wit_parser::TypeOwner::Interface(id) => self.interface_ident(
162+
package_id,
163+
None,
164+
self.resolve.interfaces.get(id).unwrap(),
165+
),
178166
_ => panic!("Type not part of an interface"),
179167
};
180168
let local_type_name = type_def.name.clone().unwrap();
181169
let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
182170
if underlying_local_type_name == local_type_name {
183-
output.use_type(interface_name, local_type_name, None);
171+
output.use_type(interface_ident, local_type_name, None);
184172
} else {
185173
output.use_type(
186-
interface_name,
174+
interface_ident,
187175
underlying_local_type_name,
188176
Some(local_type_name.into()),
189177
);
@@ -488,6 +476,51 @@ impl<'a> Converter<'a> {
488476
}
489477
output
490478
}
479+
480+
fn interface_ident(
481+
&self,
482+
package_id: PackageId,
483+
world_key: Option<&wit_parser::WorldKey>,
484+
interface: &wit_parser::Interface,
485+
) -> Ident {
486+
match &interface.name {
487+
Some(name) => {
488+
// Standalone
489+
if interface.package == Some(package_id) {
490+
Ident::new(name.clone())
491+
} else {
492+
let package = interface
493+
.package
494+
.map(|package_id| self.resolve.packages.get(package_id).unwrap());
495+
496+
match package {
497+
Some(package) => Ident::new(format!(
498+
"{}:{}/{}{}",
499+
package.name.namespace,
500+
package.name.name,
501+
name,
502+
package
503+
.name
504+
.version
505+
.as_ref()
506+
.map(|version| format!("@{}", version))
507+
.unwrap_or_else(|| "".to_string())
508+
)),
509+
None => Ident::new(name.clone()),
510+
}
511+
}
512+
}
513+
None => match world_key {
514+
Some(world_key) => match world_key {
515+
wit_parser::WorldKey::Name(name) => Ident::new(name.clone()),
516+
wit_parser::WorldKey::Interface(_) => {
517+
unreachable!("inlined interface must have a world key name")
518+
}
519+
},
520+
None => panic!("inlined interface requires a world key"),
521+
},
522+
}
523+
}
491524
}
492525

493526
fn clean_func_name(resource_name: &str, method_name: &str) -> String {

crates/wit-encoder/src/world.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl World {
3131
self.name = name.into();
3232
}
3333

34-
pub fn name(&mut self) -> &Ident {
34+
pub fn name(&self) -> &Ident {
3535
&self.name
3636
}
3737

@@ -254,7 +254,20 @@ impl WorldNamedInterface {
254254
docs: None,
255255
}
256256
}
257-
pub fn docs(&mut self, docs: Option<impl Into<Docs>>) {
257+
258+
pub fn set_name(&mut self, name: impl Into<Ident>) {
259+
self.name = name.into();
260+
}
261+
262+
pub fn name(&self) -> &Ident {
263+
&self.name
264+
}
265+
266+
pub fn set_docs(&mut self, docs: Option<impl Into<Docs>>) {
258267
self.docs = docs.map(|d| d.into());
259268
}
269+
270+
pub fn docs(&self) -> Option<&Docs> {
271+
self.docs.as_ref()
272+
}
260273
}

0 commit comments

Comments
 (0)