Skip to content

Commit 8f17e78

Browse files
authored
wit-encoder: Implement world uses and sort interface and world items, uses (#1910)
* wit-encoder: implement world uses and sort interface and world items, uses * update round trip test
1 parent 09175fa commit 8f17e78

File tree

4 files changed

+156
-53
lines changed

4 files changed

+156
-53
lines changed

crates/wit-encoder/src/from_parser.rs

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ impl<'a> Converter<'a> {
8484
output.item(WorldItem::function_import(func));
8585
}
8686
}
87-
wit_parser::WorldItem::Type(_) => {
88-
todo!();
87+
wit_parser::WorldItem::Type(type_id) => {
88+
let (target, item, rename) = self.convert_world_item_type(package_id, *type_id);
89+
output.use_type(target, item, rename)
8990
}
9091
}
9192
}
93+
9294
for (key, item) in &world.exports {
9395
match item {
9496
wit_parser::WorldItem::Interface { id, .. } => {
@@ -110,15 +112,42 @@ impl<'a> Converter<'a> {
110112
output.item(WorldItem::function_export(func));
111113
}
112114
}
113-
wit_parser::WorldItem::Type(_) => {
114-
todo!();
115+
wit_parser::WorldItem::Type(type_id) => {
116+
let (target, item, rename) = self.convert_world_item_type(package_id, *type_id);
117+
output.use_type(target, item, rename)
115118
}
116119
}
117120
}
118121

122+
output.uses_mut().sort();
123+
output.items_mut().sort();
124+
119125
output
120126
}
121127

128+
fn convert_world_item_type(
129+
&self,
130+
package_id: PackageId,
131+
type_id: wit_parser::TypeId,
132+
) -> (Ident, Ident, Option<Ident>) {
133+
let type_def = self.resolve.types.get(type_id).unwrap();
134+
let underlying_type_def = self.underlying_type_def(&type_def);
135+
let interface_ident = self
136+
.type_def_owner_interface_ident(package_id, underlying_type_def)
137+
.expect("Type not part of an interface");
138+
let local_type_name = type_def.name.clone().unwrap();
139+
let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
140+
if underlying_local_type_name == local_type_name {
141+
(interface_ident, local_type_name.into(), None)
142+
} else {
143+
(
144+
interface_ident,
145+
underlying_local_type_name.into(),
146+
Some(local_type_name.into()),
147+
)
148+
}
149+
}
150+
122151
fn convert_interface(
123152
&self,
124153
package_id: PackageId,
@@ -140,31 +169,16 @@ impl<'a> Converter<'a> {
140169
}
141170
for (_, type_id) in &interface.types {
142171
let type_def = self.resolve.types.get(*type_id).unwrap();
143-
144-
let underlying_type_def = match &type_def.kind {
145-
wit_parser::TypeDefKind::Type(type_) => match &type_ {
146-
wit_parser::Type::Id(type_id) => {
147-
let type_def = self.resolve.types.get(*type_id).unwrap();
148-
type_def
149-
}
150-
_ => type_def,
151-
},
152-
_ => type_def,
153-
};
172+
let underlying_type_def = self.underlying_type_def(&type_def);
154173

155174
if underlying_type_def.owner == owner {
156175
if let Some(type_def) = self.convert_type_def(type_def, *type_id) {
157176
output.item(InterfaceItem::TypeDef(type_def));
158177
}
159178
} else {
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-
),
166-
_ => panic!("Type not part of an interface"),
167-
};
179+
let interface_ident = self
180+
.type_def_owner_interface_ident(package_id, underlying_type_def)
181+
.expect("Type not part of an interface");
168182
let local_type_name = type_def.name.clone().unwrap();
169183
let underlying_local_type_name = underlying_type_def.name.clone().unwrap();
170184
if underlying_local_type_name == local_type_name {
@@ -179,6 +193,9 @@ impl<'a> Converter<'a> {
179193
}
180194
}
181195

196+
output.uses_mut().sort();
197+
output.items_mut().sort();
198+
182199
output
183200
}
184201

@@ -521,6 +538,31 @@ impl<'a> Converter<'a> {
521538
},
522539
}
523540
}
541+
542+
fn underlying_type_def(&'a self, type_def: &'a wit_parser::TypeDef) -> &'a wit_parser::TypeDef {
543+
match &type_def.kind {
544+
wit_parser::TypeDefKind::Type(type_) => match &type_ {
545+
wit_parser::Type::Id(type_id) => {
546+
let type_def = self.resolve.types.get(*type_id).unwrap();
547+
type_def
548+
}
549+
_ => type_def,
550+
},
551+
_ => type_def,
552+
}
553+
}
554+
555+
fn type_def_owner_interface_ident(
556+
&self,
557+
package_id: PackageId,
558+
type_def: &wit_parser::TypeDef,
559+
) -> Option<Ident> {
560+
if let wit_parser::TypeOwner::Interface(id) = type_def.owner {
561+
Some(self.interface_ident(package_id, None, self.resolve.interfaces.get(id).unwrap()))
562+
} else {
563+
None
564+
}
565+
}
524566
}
525567

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

crates/wit-encoder/src/world.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ pub struct World {
99
/// The WIT identifier name of this world.
1010
name: Ident,
1111

12+
/// Interface uses
13+
uses: Vec<Use>,
14+
1215
/// All imported and exported items into this world.
1316
items: Vec<WorldItem>,
1417

@@ -21,6 +24,7 @@ impl World {
2124
pub fn new(name: impl Into<Ident>) -> Self {
2225
Self {
2326
name: name.into(),
27+
uses: vec![],
2428
items: vec![],
2529
docs: None,
2630
}
@@ -69,8 +73,34 @@ impl World {
6973
pub fn include(&mut self, include: Include) {
7074
self.item(WorldItem::Include(include));
7175
}
76+
77+
pub fn uses(&self) -> &[Use] {
78+
&self.uses
79+
}
80+
pub fn uses_mut(&mut self) -> &mut [Use] {
81+
&mut self.uses
82+
}
7283
pub fn use_(&mut self, use_: Use) {
73-
self.item(WorldItem::Use(use_));
84+
self.uses.push(use_);
85+
}
86+
pub fn use_type(
87+
&mut self,
88+
target: impl Into<Ident>,
89+
item: impl Into<Ident>,
90+
rename: Option<Ident>,
91+
) {
92+
let target = target.into();
93+
let use_ = self.uses.iter_mut().find(|u| u.target() == &target);
94+
match use_ {
95+
Some(use_) => use_.item(item, rename),
96+
None => {
97+
self.use_({
98+
let mut use_ = Use::new(target);
99+
use_.item(item, rename);
100+
use_
101+
});
102+
}
103+
}
74104
}
75105

76106
pub fn docs(&self) -> Option<&Docs> {
@@ -105,6 +135,7 @@ impl Render for World {
105135
}
106136
write!(f, "{}world {} {{\n", opts.spaces(), self.name)?;
107137
let opts = &opts.indent();
138+
self.uses.render(f, opts)?;
108139
for item in &self.items {
109140
match item {
110141
WorldItem::InlineInterfaceImport(interface) => {
@@ -165,7 +196,6 @@ impl Render for World {
165196
render_function(f, opts, function)?;
166197
}
167198
WorldItem::Include(include) => include.render(f, opts)?,
168-
WorldItem::Use(use_) => use_.render(f, opts)?,
169199
}
170200
}
171201
let opts = &opts.outdent();
@@ -198,9 +228,6 @@ pub enum WorldItem {
198228

199229
/// Include type
200230
Include(Include),
201-
202-
/// Use
203-
Use(Use),
204231
}
205232

206233
impl WorldItem {

crates/wit-encoder/tests/deps.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ const MAIN_PACKAGE_SOURCE: &str = indoc::indoc! {"
1010
use foo:dep-a/dep-a-interface-b.{ ra };
1111
}
1212
13-
interface main-interface-b {}
13+
interface main-interface-b {
14+
record mb {
15+
x: f32,
16+
}
17+
}
1418
1519
interface main-interface-c {}
1620
@@ -19,14 +23,17 @@ const MAIN_PACKAGE_SOURCE: &str = indoc::indoc! {"
1923
interface main-interface-e {}
2024
2125
world main-world-a {
26+
use foo:dep-c/dep-c-interface-b.{ cb, cb as cbcb };
2227
import foo:dep-c/dep-c-interface-a;
2328
export foo:dep-c/dep-c-interface-b;
2429
include foo:dep-c/dep-c-world-a;
2530
31+
use foo:dep-b/dep-b-interface-b@1.2.3.{ bb, bb as bbbb };
2632
import foo:dep-b/dep-b-interface-a@1.2.3;
2733
export foo:dep-b/dep-b-interface-b@1.2.3;
2834
include foo:dep-b/dep-b-world-b@1.2.3;
2935
36+
use main-interface-b.{ mb, mb as mbmb };
3037
import main-interface-b;
3138
export main-interface-a;
3239
include main-world-b;
@@ -45,7 +52,11 @@ const MAIN_PACKAGE_RESOLVED_ENCODED: &str = indoc::indoc! {"
4552
use foo:dep-a/dep-a-interface-b.{ ra };
4653
}
4754
48-
interface main-interface-b {}
55+
interface main-interface-b {
56+
record mb {
57+
x: f32,
58+
}
59+
}
4960
5061
interface main-interface-c {}
5162
@@ -59,16 +70,21 @@ const MAIN_PACKAGE_RESOLVED_ENCODED: &str = indoc::indoc! {"
5970
}
6071
6172
world main-world-a {
62-
import foo:dep-c/dep-c-interface-a;
73+
use foo:dep-b/dep-b-interface-b@1.2.3.{ bb, bb as bbbb };
74+
use foo:dep-c/dep-c-interface-b.{ cb, cb as cbcb };
75+
use main-interface-b.{ mb, mb as mbmb };
76+
import foo:dep-a/dep-a-interface-b;
6377
import foo:dep-b/dep-b-interface-a@1.2.3;
64-
import main-interface-b;
78+
import foo:dep-b/dep-b-interface-b@1.2.3;
79+
import foo:dep-c/dep-c-interface-a;
80+
import foo:dep-c/dep-c-interface-b;
6581
import foo:dep-c/dep-c-interface-c;
82+
import main-interface-b;
6683
import main-interface-d;
67-
import foo:dep-a/dep-a-interface-b;
68-
export foo:dep-c/dep-c-interface-b;
6984
export foo:dep-b/dep-b-interface-b@1.2.3;
70-
export main-interface-a;
85+
export foo:dep-c/dep-c-interface-b;
7186
export foo:dep-c/dep-c-interface-d;
87+
export main-interface-a;
7288
export main-interface-d;
7389
}
7490
"};
@@ -96,6 +112,10 @@ const DEP_PACKAGE_B: &str = indoc::indoc! {"
96112
97113
interface dep-b-interface-b {
98114
use foo:dep-c/dep-c-interface-a.{a};
115+
116+
record bb {
117+
x: f32,
118+
}
99119
}
100120
101121
world dep-b-world-a {
@@ -115,7 +135,11 @@ const DEP_PACKAGE_C: &str = indoc::indoc! {"
115135
}
116136
}
117137
118-
interface dep-c-interface-b {}
138+
interface dep-c-interface-b {
139+
record cb {
140+
x: f32,
141+
}
142+
}
119143
120144
interface dep-c-interface-c {}
121145

0 commit comments

Comments
 (0)