1use anyhow::{Result, anyhow, bail};
2use std::borrow::Cow;
3use std::collections::HashMap;
4use std::fmt::Display;
5use std::mem;
6use std::ops::Deref;
7use wit_parser::*;
8
9pub struct WitPrinter<O: Output = OutputToString> {
11 pub output: O,
13
14 any_items: bool,
17
18 emit_docs: bool,
20}
21
22impl Default for WitPrinter {
23 fn default() -> Self {
24 Self::new(OutputToString::default())
25 }
26}
27
28impl<O: Output> WitPrinter<O> {
29 pub fn new(output: O) -> Self {
31 Self {
32 output,
33 any_items: false,
34 emit_docs: true,
35 }
36 }
37
38 pub fn print(&mut self, resolve: &Resolve, pkg: PackageId, nested: &[PackageId]) -> Result<()> {
43 self.print_package(resolve, pkg, true)?;
44 for (i, pkg_id) in nested.iter().enumerate() {
45 if i > 0 {
46 self.output.newline();
47 self.output.newline();
48 }
49 self.print_package(resolve, *pkg_id, false)?;
50 }
51 Ok(())
52 }
53
54 pub fn emit_docs(&mut self, enabled: bool) -> &mut Self {
58 self.emit_docs = enabled;
59 self
60 }
61
62 pub fn print_package(
66 &mut self,
67 resolve: &Resolve,
68 pkg: PackageId,
69 is_main: bool,
70 ) -> Result<()> {
71 let pkg = &resolve.packages[pkg];
72 self.print_package_outer(pkg)?;
73
74 if is_main {
75 self.output.semicolon();
76 self.output.newline();
77 } else {
78 self.output.indent_start();
79 }
80
81 for (name, id) in pkg.interfaces.iter() {
82 self.print_interface_outer(resolve, *id, name)?;
83 self.output.indent_start();
84 self.print_interface(resolve, *id)?;
85 self.output.indent_end();
86 if is_main {
87 self.output.newline();
88 }
89 }
90
91 for (name, id) in pkg.worlds.iter() {
92 self.print_docs(&resolve.worlds[*id].docs);
93 self.print_stability(&resolve.worlds[*id].stability);
94 self.output.keyword("world");
95 self.output.str(" ");
96 self.print_name_type(name, TypeKind::WorldDeclaration);
97 self.output.indent_start();
98 self.print_world(resolve, *id)?;
99 self.output.indent_end();
100 }
101 if !is_main {
102 self.output.indent_end();
103 }
104 Ok(())
105 }
106
107 pub fn print_package_outer(&mut self, pkg: &Package) -> Result<()> {
110 self.print_docs(&pkg.docs);
111 self.output.keyword("package");
112 self.output.str(" ");
113 self.print_name_type(&pkg.name.namespace, TypeKind::NamespaceDeclaration);
114 self.output.str(":");
115 self.print_name_type(&pkg.name.name, TypeKind::PackageNameDeclaration);
116 if let Some(version) = &pkg.name.version {
117 self.print_name_type(&format!("@{version}"), TypeKind::VersionDeclaration);
118 }
119 Ok(())
120 }
121
122 fn new_item(&mut self) {
123 if self.any_items {
124 self.output.newline();
125 }
126 self.any_items = true;
127 }
128
129 pub fn print_interface_outer(
132 &mut self,
133 resolve: &Resolve,
134 id: InterfaceId,
135 name: &str,
136 ) -> Result<()> {
137 self.print_docs(&resolve.interfaces[id].docs);
138 self.print_stability(&resolve.interfaces[id].stability);
139 self.output.keyword("interface");
140 self.output.str(" ");
141 self.print_name_type(name, TypeKind::InterfaceDeclaration);
142 Ok(())
143 }
144
145 pub fn print_interface(&mut self, resolve: &Resolve, id: InterfaceId) -> Result<()> {
147 let prev_items = mem::replace(&mut self.any_items, false);
148 let interface = &resolve.interfaces[id];
149
150 let mut resource_funcs = HashMap::new();
151 let mut freestanding = Vec::new();
152 for (_, func) in interface.functions.iter() {
153 if let Some(id) = func.kind.resource() {
154 resource_funcs.entry(id).or_insert(Vec::new()).push(func);
155 } else {
156 freestanding.push(func);
157 }
158 }
159
160 self.print_types(
161 resolve,
162 TypeOwner::Interface(id),
163 interface
164 .types
165 .iter()
166 .map(|(name, id)| (name.as_str(), *id)),
167 &resource_funcs,
168 )?;
169
170 for func in freestanding {
171 self.new_item();
172 self.print_docs(&func.docs);
173 self.print_stability(&func.stability);
174 self.print_name_type(func.item_name(), TypeKind::FunctionFreestanding);
175 self.output.str(": ");
176 self.print_function(resolve, func)?;
177 self.output.semicolon();
178 }
179
180 self.any_items = prev_items;
181
182 Ok(())
183 }
184
185 pub fn print_types<'a>(
187 &mut self,
188 resolve: &Resolve,
189 owner: TypeOwner,
190 types: impl Iterator<Item = (&'a str, TypeId)>,
191 resource_funcs: &HashMap<TypeId, Vec<&Function>>,
192 ) -> Result<()> {
193 let mut types_to_declare = Vec::new();
196 let mut types_to_import: Vec<(_, &_, Vec<_>)> = Vec::new();
197 for (name, ty_id) in types {
198 let ty = &resolve.types[ty_id];
199 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
200 let other = &resolve.types[other];
201 match other.owner {
202 TypeOwner::None => {}
203 other_owner if owner != other_owner => {
204 let other_name = other
205 .name
206 .as_ref()
207 .ok_or_else(|| anyhow!("cannot import unnamed type"))?;
208 if let Some((owner, stability, list)) = types_to_import.last_mut() {
209 if *owner == other_owner && ty.stability == **stability {
210 list.push((name, other_name));
211 continue;
212 }
213 }
214 types_to_import.push((
215 other_owner,
216 &ty.stability,
217 vec![(name, other_name)],
218 ));
219 continue;
220 }
221 _ => {}
222 }
223 }
224
225 types_to_declare.push(ty_id);
226 }
227
228 let my_pkg = match owner {
230 TypeOwner::Interface(id) => resolve.interfaces[id].package.unwrap(),
231 TypeOwner::World(id) => resolve.worlds[id].package.unwrap(),
232 TypeOwner::None => unreachable!(),
233 };
234 for (owner, stability, tys) in types_to_import {
235 self.any_items = true;
236 self.print_stability(stability);
237 self.output.keyword("use");
238 self.output.str(" ");
239 let id = match owner {
240 TypeOwner::Interface(id) => id,
241 _ => unreachable!(),
244 };
245 self.print_path_to_interface(resolve, id, my_pkg)?;
246 self.output.str(".{"); for (i, (my_name, other_name)) in tys.into_iter().enumerate() {
248 if i > 0 {
249 self.output.str(", ");
250 }
251 if my_name == other_name {
252 self.print_name_type(my_name, TypeKind::TypeImport);
253 } else {
254 self.print_name_type(other_name, TypeKind::TypeImport);
255 self.output.str(" ");
256 self.output.keyword("as");
257 self.output.str(" ");
258 self.print_name_type(my_name, TypeKind::TypeAlias);
259 }
260 }
261 self.output.str("}"); self.output.semicolon();
263 }
264
265 for id in types_to_declare {
266 self.new_item();
267 self.print_docs(&resolve.types[id].docs);
268 self.print_stability(&resolve.types[id].stability);
269 match resolve.types[id].kind {
270 TypeDefKind::Resource => self.print_resource(
271 resolve,
272 id,
273 resource_funcs.get(&id).unwrap_or(&Vec::new()),
274 )?,
275 _ => self.declare_type(resolve, &Type::Id(id))?,
276 }
277 }
278
279 Ok(())
280 }
281
282 fn print_resource(&mut self, resolve: &Resolve, id: TypeId, funcs: &[&Function]) -> Result<()> {
283 let ty = &resolve.types[id];
284 self.output.ty("resource", TypeKind::BuiltIn);
285 self.output.str(" ");
286 self.print_name_type(
287 ty.name.as_ref().expect("resources must be named"),
288 TypeKind::Resource,
289 );
290 if funcs.is_empty() {
291 self.output.semicolon();
292 return Ok(());
293 }
294 self.output.indent_start();
295 for func in funcs {
296 self.print_docs(&func.docs);
297 self.print_stability(&func.stability);
298
299 match &func.kind {
300 FunctionKind::Constructor(_) => {}
301 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
302 self.print_name_type(func.item_name(), TypeKind::FunctionMethod);
303 self.output.str(": ");
304 }
305 FunctionKind::Static(_) | FunctionKind::AsyncStatic(_) => {
306 self.print_name_type(func.item_name(), TypeKind::FunctionStatic);
307 self.output.str(": ");
308 self.output.keyword("static");
309 self.output.str(" ");
310 }
311 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => unreachable!(),
312 }
313 self.print_function(resolve, func)?;
314 self.output.semicolon();
315 }
316 self.output.indent_end();
317
318 Ok(())
319 }
320
321 fn print_function(&mut self, resolve: &Resolve, func: &Function) -> Result<()> {
322 match &func.kind {
324 FunctionKind::AsyncFreestanding
325 | FunctionKind::AsyncMethod(_)
326 | FunctionKind::AsyncStatic(_) => {
327 self.output.keyword("async");
328 self.output.str(" ");
329 }
330 _ => {}
331 }
332
333 match &func.kind {
335 FunctionKind::Constructor(_) => {
336 self.output.keyword("constructor");
337 self.output.str("(");
338 }
339 FunctionKind::Freestanding
340 | FunctionKind::AsyncFreestanding
341 | FunctionKind::Method(_)
342 | FunctionKind::AsyncMethod(_)
343 | FunctionKind::Static(_)
344 | FunctionKind::AsyncStatic(_) => {
345 self.output.keyword("func");
346 self.output.str("(");
347 }
348 }
349
350 let params_to_skip = match &func.kind {
352 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => 1,
353 _ => 0,
354 };
355 for (i, param) in func.params.iter().skip(params_to_skip).enumerate() {
356 if i > 0 {
357 self.output.str(", ");
358 }
359 self.print_name_param(¶m.name);
360 self.output.str(": ");
361 self.print_type_name(resolve, ¶m.ty)?;
362 }
363 self.output.str(")");
364
365 if func.is_constructor_shorthand(resolve) {
367 return Ok(());
368 }
369
370 if let Some(ty) = &func.result {
371 self.output.str(" -> ");
372 self.print_type_name(resolve, ty)?;
373 }
374 Ok(())
375 }
376
377 fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
397 let prev_items = mem::replace(&mut self.any_items, false);
398 let world = &resolve.worlds[id];
399 let pkgid = world.package.unwrap();
400 let mut types = Vec::new();
401 let mut resource_funcs = HashMap::new();
402 let mut function_imports_to_print = Vec::new();
403 for (name, import) in world.imports.iter() {
404 match import {
405 WorldItem::Type { id, .. } => match name {
406 WorldKey::Name(s) => types.push((s.as_str(), *id)),
407 WorldKey::Interface(_) => unreachable!(),
408 },
409 _ => {
410 if let WorldItem::Function(f) = import {
411 if let Some(id) = f.kind.resource() {
412 resource_funcs.entry(id).or_insert(Vec::new()).push(f);
413 continue;
414 }
415 function_imports_to_print.push((name, import));
416 continue;
417 }
418 self.print_world_item(resolve, name, import, pkgid, "import")?;
419 self.any_items = true;
423 }
424 }
425 }
426 self.print_types(
427 resolve,
428 TypeOwner::World(id),
429 types.into_iter(),
430 &resource_funcs,
431 )?;
432
433 for (name, import) in function_imports_to_print {
434 self.print_world_item(resolve, name, import, pkgid, "import")?;
435 self.any_items = true;
436 }
437 if !world.exports.is_empty() {
438 self.new_item();
439 }
440 for (name, export) in world.exports.iter() {
441 self.print_world_item(resolve, name, export, pkgid, "export")?;
442 }
443 self.any_items = prev_items;
444 Ok(())
445 }
446
447 fn print_world_item(
448 &mut self,
449 resolve: &Resolve,
450 name: &WorldKey,
451 item: &WorldItem,
452 cur_pkg: PackageId,
453 import_or_export_keyword: &str,
454 ) -> Result<()> {
455 if matches!(name, WorldKey::Name(_)) {
457 self.print_docs(match item {
458 WorldItem::Interface { id, .. } => &resolve.interfaces[*id].docs,
459 WorldItem::Function(f) => &f.docs,
460 WorldItem::Type { .. } => unreachable!(),
462 });
463 }
464
465 self.print_stability(item.stability(resolve));
466 self.output.keyword(import_or_export_keyword);
467 self.output.str(" ");
468 match name {
469 WorldKey::Name(name) => {
470 match item {
471 WorldItem::Interface { id, .. } => {
472 self.print_name_type(name, TypeKind::Other);
473 self.output.str(": ");
474 if resolve.interfaces[*id].name.is_none() {
475 self.output.keyword("interface");
477 self.output.indent_start();
478 self.print_interface(resolve, *id)?;
479 self.output.indent_end();
480 } else {
481 self.print_path_to_interface(resolve, *id, cur_pkg)?;
483 self.output.semicolon();
484 }
485 }
486 WorldItem::Function(f) => {
487 self.print_name_type(&f.name, TypeKind::Other);
488 self.output.str(": ");
489 self.print_function(resolve, f)?;
490 self.output.semicolon();
491 }
492 WorldItem::Type { .. } => unreachable!(),
494 }
495 }
496 WorldKey::Interface(id) => {
497 match item {
498 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
499 _ => unreachable!(),
500 }
501 self.print_path_to_interface(resolve, *id, cur_pkg)?;
502 self.output.semicolon();
503 }
504 }
505 Ok(())
506 }
507
508 fn print_path_to_interface(
509 &mut self,
510 resolve: &Resolve,
511 interface: InterfaceId,
512 cur_pkg: PackageId,
513 ) -> Result<()> {
514 let iface = &resolve.interfaces[interface];
515 if iface.package == Some(cur_pkg) {
516 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
517 } else {
518 let pkg = &resolve.packages[iface.package.unwrap()].name;
519 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
520 self.output.str(":");
521 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
522 self.output.str("/");
523 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
524 if let Some(version) = &pkg.version {
525 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
526 }
527 }
528 Ok(())
529 }
530
531 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
533 match ty {
534 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
535 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
536 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
537 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
538 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
539 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
540 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
541 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
542 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
543 Type::F32 => self.output.ty("f32", TypeKind::BuiltIn),
544 Type::F64 => self.output.ty("f64", TypeKind::BuiltIn),
545 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
546 Type::String => self.output.ty("string", TypeKind::BuiltIn),
547 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
548
549 Type::Id(id) => {
550 let ty = &resolve.types[*id];
551 if let Some(name) = &ty.name {
552 self.print_name_type(name, TypeKind::Other);
553 return Ok(());
554 }
555
556 match &ty.kind {
557 TypeDefKind::Handle(h) => {
558 self.print_handle_type(resolve, h, false)?;
559 }
560 TypeDefKind::Resource => {
561 bail!("resolve has an unnamed resource type");
562 }
563 TypeDefKind::Tuple(t) => {
564 self.print_tuple_type(resolve, t)?;
565 }
566 TypeDefKind::Option(t) => {
567 self.print_option_type(resolve, t)?;
568 }
569 TypeDefKind::Result(t) => {
570 self.print_result_type(resolve, t)?;
571 }
572 TypeDefKind::Record(_) => {
573 bail!("resolve has an unnamed record type");
574 }
575 TypeDefKind::Flags(_) => {
576 bail!("resolve has unnamed flags type")
577 }
578 TypeDefKind::Enum(_) => {
579 bail!("resolve has unnamed enum type")
580 }
581 TypeDefKind::Variant(_) => {
582 bail!("resolve has unnamed variant type")
583 }
584 TypeDefKind::List(ty) => {
585 self.output.ty("list", TypeKind::BuiltIn);
586 self.output.generic_args_start();
587 self.print_type_name(resolve, ty)?;
588 self.output.generic_args_end();
589 }
590 TypeDefKind::Map(key_ty, value_ty) => {
591 self.output.ty("map", TypeKind::BuiltIn);
592 self.output.generic_args_start();
593 self.print_type_name(resolve, key_ty)?;
594 self.output.str(", ");
595 self.print_type_name(resolve, value_ty)?;
596 self.output.generic_args_end();
597 }
598 TypeDefKind::FixedLengthList(ty, size) => {
599 self.output.ty("list", TypeKind::BuiltIn);
600 self.output.generic_args_start();
601 self.print_type_name(resolve, ty)?;
602 self.output.push_str(&format!(", {}", *size));
603 self.output.generic_args_end();
604 }
605 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
606 TypeDefKind::Future(ty) => {
607 if let Some(ty) = ty {
608 self.output.push_str("future<");
609 self.print_type_name(resolve, ty)?;
610 self.output.push_str(">");
611 } else {
612 self.output.push_str("future");
613 }
614 }
615 TypeDefKind::Stream(ty) => {
616 if let Some(ty) = ty {
617 self.output.push_str("stream<");
618 self.print_type_name(resolve, ty)?;
619 self.output.push_str(">");
620 } else {
621 self.output.push_str("stream");
622 }
623 }
624 TypeDefKind::Unknown => unreachable!(),
625 }
626 }
627 }
628
629 Ok(())
630 }
631
632 fn print_handle_type(
633 &mut self,
634 resolve: &Resolve,
635 handle: &Handle,
636 force_handle_type_printed: bool,
637 ) -> Result<()> {
638 match handle {
639 Handle::Own(ty) => {
640 let ty = &resolve.types[*ty];
641 if force_handle_type_printed {
642 self.output.ty("own", TypeKind::BuiltIn);
643 self.output.generic_args_start();
644 }
645 self.print_name_type(
646 ty.name
647 .as_ref()
648 .ok_or_else(|| anyhow!("unnamed resource type"))?,
649 TypeKind::Resource,
650 );
651 if force_handle_type_printed {
652 self.output.generic_args_end();
653 }
654 }
655
656 Handle::Borrow(ty) => {
657 self.output.ty("borrow", TypeKind::BuiltIn);
658 self.output.generic_args_start();
659 let ty = &resolve.types[*ty];
660 self.print_name_type(
661 ty.name
662 .as_ref()
663 .ok_or_else(|| anyhow!("unnamed resource type"))?,
664 TypeKind::Resource,
665 );
666 self.output.generic_args_end();
667 }
668 }
669
670 Ok(())
671 }
672
673 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
674 self.output.ty("tuple", TypeKind::BuiltIn);
675 self.output.generic_args_start();
676 for (i, ty) in tuple.types.iter().enumerate() {
677 if i > 0 {
678 self.output.str(", ");
679 }
680 self.print_type_name(resolve, ty)?;
681 }
682 self.output.generic_args_end();
683
684 Ok(())
685 }
686
687 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
688 self.output.ty("option", TypeKind::BuiltIn);
689 self.output.generic_args_start();
690 self.print_type_name(resolve, payload)?;
691 self.output.generic_args_end();
692 Ok(())
693 }
694
695 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
696 match result {
697 Result_ {
698 ok: Some(ok),
699 err: Some(err),
700 } => {
701 self.output.ty("result", TypeKind::BuiltIn);
702 self.output.generic_args_start();
703 self.print_type_name(resolve, ok)?;
704 self.output.str(", ");
705 self.print_type_name(resolve, err)?;
706 self.output.generic_args_end();
707 }
708 Result_ {
709 ok: None,
710 err: Some(err),
711 } => {
712 self.output.ty("result", TypeKind::BuiltIn);
713 self.output.generic_args_start();
714 self.output.str("_, ");
715 self.print_type_name(resolve, err)?;
716 self.output.generic_args_end();
717 }
718 Result_ {
719 ok: Some(ok),
720 err: None,
721 } => {
722 self.output.ty("result", TypeKind::BuiltIn);
723 self.output.generic_args_start();
724 self.print_type_name(resolve, ok)?;
725 self.output.generic_args_end();
726 }
727 Result_ {
728 ok: None,
729 err: None,
730 } => {
731 self.output.ty("result", TypeKind::BuiltIn);
732 }
733 }
734 Ok(())
735 }
736
737 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
738 match ty {
739 Type::Bool
740 | Type::U8
741 | Type::U16
742 | Type::U32
743 | Type::U64
744 | Type::S8
745 | Type::S16
746 | Type::S32
747 | Type::S64
748 | Type::F32
749 | Type::F64
750 | Type::Char
751 | Type::String
752 | Type::ErrorContext => return Ok(()),
753
754 Type::Id(id) => {
755 let ty = &resolve.types[*id];
756 match &ty.kind {
757 TypeDefKind::Handle(h) => {
758 self.declare_handle(resolve, ty.name.as_deref(), h)?
759 }
760 TypeDefKind::Resource => panic!("resources should be processed separately"),
761 TypeDefKind::Record(r) => {
762 self.declare_record(resolve, ty.name.as_deref(), r)?
763 }
764 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
765 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
766 TypeDefKind::Variant(v) => {
767 self.declare_variant(resolve, ty.name.as_deref(), v)?
768 }
769 TypeDefKind::Option(t) => {
770 self.declare_option(resolve, ty.name.as_deref(), t)?
771 }
772 TypeDefKind::Result(r) => {
773 self.declare_result(resolve, ty.name.as_deref(), r)?
774 }
775 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
776 TypeDefKind::List(inner) => {
777 self.declare_list(resolve, ty.name.as_deref(), inner)?
778 }
779 TypeDefKind::Map(key, value) => {
780 self.declare_map(resolve, ty.name.as_deref(), key, value)?
781 }
782 TypeDefKind::FixedLengthList(inner, size) => {
783 self.declare_fixed_length_list(resolve, ty.name.as_deref(), inner, *size)?
784 }
785 TypeDefKind::Type(inner) => match ty.name.as_deref() {
786 Some(name) => {
787 self.output.keyword("type");
788 self.output.str(" ");
789 self.print_name_type(name, TypeKind::TypeName);
790 self.output.str(" = ");
791 self.print_type_name(resolve, inner)?;
792 self.output.semicolon();
793 }
794 None => bail!("unnamed type in document"),
795 },
796 TypeDefKind::Future(inner) => {
797 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
798 }
799 TypeDefKind::Stream(inner) => {
800 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
801 }
802 TypeDefKind::Unknown => unreachable!(),
803 }
804 }
805 }
806 Ok(())
807 }
808
809 fn declare_handle(
810 &mut self,
811 resolve: &Resolve,
812 name: Option<&str>,
813 handle: &Handle,
814 ) -> Result<()> {
815 match name {
816 Some(name) => {
817 self.output.keyword("type");
818 self.output.str(" ");
819 self.print_name_type(name, TypeKind::Resource);
820 self.output.str(" = ");
821 self.print_handle_type(resolve, handle, true)?;
827 self.output.semicolon();
828
829 Ok(())
830 }
831 None => bail!("document has unnamed handle type"),
832 }
833 }
834
835 fn declare_record(
836 &mut self,
837 resolve: &Resolve,
838 name: Option<&str>,
839 record: &Record,
840 ) -> Result<()> {
841 match name {
842 Some(name) => {
843 self.output.keyword("record");
844 self.output.str(" ");
845 self.print_name_type(name, TypeKind::Record);
846 self.output.indent_start();
847 for field in &record.fields {
848 self.print_docs(&field.docs);
849 self.print_name_param(&field.name);
850 self.output.str(": ");
851 self.print_type_name(resolve, &field.ty)?;
852 self.output.str(",");
853 self.output.newline();
854 }
855 self.output.indent_end();
856 Ok(())
857 }
858 None => bail!("document has unnamed record type"),
859 }
860 }
861
862 fn declare_tuple(
863 &mut self,
864 resolve: &Resolve,
865 name: Option<&str>,
866 tuple: &Tuple,
867 ) -> Result<()> {
868 if let Some(name) = name {
869 self.output.keyword("type");
870 self.output.str(" ");
871 self.print_name_type(name, TypeKind::Tuple);
872 self.output.str(" = ");
873 self.print_tuple_type(resolve, tuple)?;
874 self.output.semicolon();
875 }
876 Ok(())
877 }
878
879 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
880 match name {
881 Some(name) => {
882 self.output.keyword("flags");
883 self.output.str(" ");
884 self.print_name_type(name, TypeKind::Flags);
885 self.output.indent_start();
886 for flag in &flags.flags {
887 self.print_docs(&flag.docs);
888 self.print_name_case(&flag.name);
889 self.output.str(",");
890 self.output.newline();
891 }
892 self.output.indent_end();
893 }
894 None => bail!("document has unnamed flags type"),
895 }
896 Ok(())
897 }
898
899 fn declare_variant(
900 &mut self,
901 resolve: &Resolve,
902 name: Option<&str>,
903 variant: &Variant,
904 ) -> Result<()> {
905 let name = match name {
906 Some(name) => name,
907 None => bail!("document has unnamed variant type"),
908 };
909 self.output.keyword("variant");
910 self.output.str(" ");
911 self.print_name_type(name, TypeKind::Variant);
912 self.output.indent_start();
913 for case in &variant.cases {
914 self.print_docs(&case.docs);
915 self.print_name_case(&case.name);
916 if let Some(ty) = case.ty {
917 self.output.str("(");
918 self.print_type_name(resolve, &ty)?;
919 self.output.str(")");
920 }
921 self.output.str(",");
922 self.output.newline();
923 }
924 self.output.indent_end();
925 Ok(())
926 }
927
928 fn declare_option(
929 &mut self,
930 resolve: &Resolve,
931 name: Option<&str>,
932 payload: &Type,
933 ) -> Result<()> {
934 if let Some(name) = name {
935 self.output.keyword("type");
936 self.output.str(" ");
937 self.print_name_type(name, TypeKind::Option);
938 self.output.str(" = ");
939 self.print_option_type(resolve, payload)?;
940 self.output.semicolon();
941 }
942 Ok(())
943 }
944
945 fn declare_result(
946 &mut self,
947 resolve: &Resolve,
948 name: Option<&str>,
949 result: &Result_,
950 ) -> Result<()> {
951 if let Some(name) = name {
952 self.output.keyword("type");
953 self.output.str(" ");
954 self.print_name_type(name, TypeKind::Result);
955 self.output.str(" = ");
956 self.print_result_type(resolve, result)?;
957 self.output.semicolon();
958 }
959 Ok(())
960 }
961
962 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
963 let name = match name {
964 Some(name) => name,
965 None => bail!("document has unnamed enum type"),
966 };
967 self.output.keyword("enum");
968 self.output.str(" ");
969 self.print_name_type(name, TypeKind::Enum);
970 self.output.indent_start();
971 for case in &enum_.cases {
972 self.print_docs(&case.docs);
973 self.print_name_case(&case.name);
974 self.output.str(",");
975 self.output.newline();
976 }
977 self.output.indent_end();
978 Ok(())
979 }
980
981 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
982 if let Some(name) = name {
983 self.output.keyword("type");
984 self.output.str(" ");
985 self.print_name_type(name, TypeKind::List);
986 self.output.str(" = ");
987 self.output.ty("list", TypeKind::BuiltIn);
988 self.output.str("<");
989 self.print_type_name(resolve, ty)?;
990 self.output.str(">");
991 self.output.semicolon();
992 return Ok(());
993 }
994
995 Ok(())
996 }
997
998 fn declare_map(
999 &mut self,
1000 resolve: &Resolve,
1001 name: Option<&str>,
1002 key_ty: &Type,
1003 value_ty: &Type,
1004 ) -> Result<()> {
1005 if let Some(name) = name {
1006 self.output.keyword("type");
1007 self.output.str(" ");
1008 self.print_name_type(name, TypeKind::Map);
1009 self.output.str(" = ");
1010 self.output.ty("map", TypeKind::BuiltIn);
1011 self.output.str("<");
1012 self.print_type_name(resolve, key_ty)?;
1013 self.output.str(", ");
1014 self.print_type_name(resolve, value_ty)?;
1015 self.output.str(">");
1016 self.output.semicolon();
1017 return Ok(());
1018 }
1019
1020 Ok(())
1021 }
1022
1023 fn declare_fixed_length_list(
1024 &mut self,
1025 resolve: &Resolve,
1026 name: Option<&str>,
1027 ty: &Type,
1028 elements: u32,
1029 ) -> Result<()> {
1030 if let Some(name) = name {
1031 self.output.keyword("type");
1032 self.output.str(" ");
1033 self.print_name_type(name, TypeKind::List);
1034 self.output.str(" = ");
1035 self.output.ty("list", TypeKind::BuiltIn);
1036 self.output.str("<");
1037 self.print_type_name(resolve, ty)?;
1038 self.output.str(&format!(", {elements}"));
1039 self.output.str(">");
1040 self.output.semicolon();
1041 return Ok(());
1042 }
1043
1044 Ok(())
1045 }
1046
1047 fn declare_stream(
1048 &mut self,
1049 resolve: &Resolve,
1050 name: Option<&str>,
1051 ty: Option<&Type>,
1052 ) -> Result<()> {
1053 if let Some(name) = name {
1054 self.output.keyword("type");
1055 self.output.str(" ");
1056 self.print_name_type(name, TypeKind::Stream);
1057 self.output.str(" = ");
1058 self.output.ty("stream", TypeKind::BuiltIn);
1059 if let Some(ty) = ty {
1060 self.output.str("<");
1061 self.print_type_name(resolve, ty)?;
1062 self.output.str(">");
1063 }
1064 self.output.semicolon();
1065 }
1066
1067 Ok(())
1068 }
1069
1070 fn declare_future(
1071 &mut self,
1072 resolve: &Resolve,
1073 name: Option<&str>,
1074 ty: Option<&Type>,
1075 ) -> Result<()> {
1076 if let Some(name) = name {
1077 self.output.keyword("type");
1078 self.output.str(" ");
1079 self.print_name_type(name, TypeKind::Future);
1080 self.output.str(" = ");
1081 self.output.ty("future", TypeKind::BuiltIn);
1082 if let Some(ty) = ty {
1083 self.output.str("<");
1084 self.print_type_name(resolve, ty)?;
1085 self.output.str(">");
1086 }
1087 self.output.semicolon();
1088 }
1089
1090 Ok(())
1091 }
1092
1093 fn escape_name(name: &str) -> Cow<'_, str> {
1094 if is_keyword(name) {
1095 Cow::Owned(format!("%{name}"))
1096 } else {
1097 Cow::Borrowed(name)
1098 }
1099 }
1100
1101 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1102 self.output.ty(Self::escape_name(name).deref(), kind);
1103 }
1104
1105 fn print_name_param(&mut self, name: &str) {
1106 self.output.param(Self::escape_name(name).deref());
1107 }
1108
1109 fn print_name_case(&mut self, name: &str) {
1110 self.output.case(Self::escape_name(name).deref());
1111 }
1112
1113 fn print_docs(&mut self, docs: &Docs) {
1114 if self.emit_docs {
1115 if let Some(contents) = &docs.contents {
1116 for line in contents.lines() {
1117 self.output.doc(line);
1118 }
1119 }
1120 }
1121 }
1122
1123 fn print_stability(&mut self, stability: &Stability) {
1124 match stability {
1125 Stability::Unknown => {}
1126 Stability::Stable { since, deprecated } => {
1127 self.output.keyword("@since");
1128 self.output.str("(");
1129 self.output.keyword("version");
1130 self.output.str(" = ");
1131 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1132 self.output.str(")");
1133 self.output.newline();
1134 if let Some(version) = deprecated {
1135 self.output.keyword("@deprecated");
1136 self.output.str("(");
1137 self.output.keyword("version");
1138 self.output.str(" = ");
1139 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1140 self.output.str(")");
1141 self.output.newline();
1142 }
1143 }
1144 Stability::Unstable {
1145 feature,
1146 deprecated,
1147 } => {
1148 self.output.keyword("@unstable");
1149 self.output.str("(");
1150 self.output.keyword("feature");
1151 self.output.str(" = ");
1152 self.output.str(feature);
1153 self.output.str(")");
1154 self.output.newline();
1155 if let Some(version) = deprecated {
1156 self.output.keyword("@deprecated");
1157 self.output.str("(");
1158 self.output.keyword("version");
1159 self.output.str(" = ");
1160 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1161 self.output.str(")");
1162 self.output.newline();
1163 }
1164 }
1165 }
1166 }
1167}
1168
1169fn is_keyword(name: &str) -> bool {
1170 matches!(
1171 name,
1172 "use"
1173 | "type"
1174 | "func"
1175 | "u8"
1176 | "u16"
1177 | "u32"
1178 | "u64"
1179 | "s8"
1180 | "s16"
1181 | "s32"
1182 | "s64"
1183 | "f32"
1184 | "f64"
1185 | "float32"
1186 | "float64"
1187 | "char"
1188 | "resource"
1189 | "record"
1190 | "flags"
1191 | "variant"
1192 | "enum"
1193 | "bool"
1194 | "string"
1195 | "option"
1196 | "result"
1197 | "future"
1198 | "stream"
1199 | "list"
1200 | "own"
1201 | "borrow"
1202 | "_"
1203 | "as"
1204 | "from"
1205 | "static"
1206 | "interface"
1207 | "tuple"
1208 | "world"
1209 | "import"
1210 | "export"
1211 | "package"
1212 | "with"
1213 | "include"
1214 | "constructor"
1215 | "error-context"
1216 | "async"
1217 | "map"
1218 )
1219}
1220
1221pub trait Output {
1227 fn push_str(&mut self, src: &str);
1235
1236 fn indent_if_needed(&mut self) -> bool;
1242
1243 fn indent_start(&mut self);
1245
1246 fn indent_end(&mut self);
1248
1249 fn indent_and_print(&mut self, src: &str) {
1252 assert!(!src.contains('\n'));
1253 let indented = self.indent_if_needed();
1254 if indented && src.starts_with(' ') {
1255 panic!("cannot add a space at the beginning of a line");
1256 }
1257 self.push_str(src);
1258 }
1259
1260 fn newline(&mut self);
1262
1263 fn keyword(&mut self, src: &str) {
1266 self.indent_and_print(src);
1267 }
1268
1269 fn ty(&mut self, src: &str, _kind: TypeKind) {
1271 self.indent_and_print(src);
1272 }
1273
1274 fn param(&mut self, src: &str) {
1276 self.indent_and_print(src);
1277 }
1278
1279 fn case(&mut self, src: &str) {
1281 self.indent_and_print(src);
1282 }
1283
1284 fn generic_args_start(&mut self) {
1286 assert!(
1287 !self.indent_if_needed(),
1288 "`generic_args_start` is never called after newline"
1289 );
1290 self.push_str("<");
1291 }
1292
1293 fn generic_args_end(&mut self) {
1295 assert!(
1296 !self.indent_if_needed(),
1297 "`generic_args_end` is never called after newline"
1298 );
1299 self.push_str(">");
1300 }
1301
1302 fn doc(&mut self, doc: &str) {
1305 assert!(!doc.contains('\n'));
1306 self.indent_if_needed();
1307 self.push_str("///");
1308 if !doc.is_empty() {
1309 self.push_str(" ");
1310 self.push_str(doc);
1311 }
1312 self.newline();
1313 }
1314
1315 fn semicolon(&mut self) {
1317 assert!(
1318 !self.indent_if_needed(),
1319 "`semicolon` is never called after newline"
1320 );
1321 self.push_str(";");
1322 self.newline();
1323 }
1324
1325 fn str(&mut self, src: &str) {
1329 self.indent_and_print(src);
1330 }
1331}
1332
1333#[non_exhaustive]
1339#[derive(Clone, Copy, Debug)]
1340pub enum TypeKind {
1341 BuiltIn,
1343 Enum,
1345 ErrorContext,
1347 Flags,
1349 FunctionFreestanding,
1352 FunctionMethod,
1354 FunctionStatic,
1356 Future,
1358 InterfaceDeclaration,
1360 InterfacePath,
1362 List,
1364 Map,
1366 NamespaceDeclaration,
1368 NamespacePath,
1370 Option,
1372 PackageNameDeclaration,
1374 PackageNamePath,
1376 Record,
1378 Resource,
1380 Result,
1382 Stream,
1384 Tuple,
1386 TypeAlias,
1388 TypeImport,
1390 TypeName,
1392 Variant,
1394 VersionDeclaration,
1396 VersionPath,
1398 VersionAnnotation,
1400 WorldDeclaration,
1402 Other,
1404}
1405
1406#[derive(Default)]
1409pub struct OutputToString {
1410 indent: usize,
1411 output: String,
1412 needs_indent: bool,
1414}
1415
1416impl Output for OutputToString {
1417 fn push_str(&mut self, src: &str) {
1418 self.output.push_str(src);
1419 }
1420
1421 fn indent_if_needed(&mut self) -> bool {
1422 if self.needs_indent {
1423 for _ in 0..self.indent {
1424 self.output.push_str(" ");
1426 }
1427 self.needs_indent = false;
1428 true
1429 } else {
1430 false
1431 }
1432 }
1433
1434 fn indent_start(&mut self) {
1435 assert!(
1436 !self.needs_indent,
1437 "`indent_start` is never called after newline"
1438 );
1439 self.output.push_str(" {");
1440 self.indent += 1;
1441 self.newline();
1442 }
1443
1444 fn indent_end(&mut self) {
1445 self.indent = self.indent.saturating_sub(1);
1450 self.indent_if_needed();
1451 self.output.push('}');
1452 self.newline();
1453 }
1454
1455 fn newline(&mut self) {
1456 self.output.push('\n');
1457 self.needs_indent = true;
1458 }
1459}
1460
1461impl From<OutputToString> for String {
1462 fn from(output: OutputToString) -> String {
1463 output.output
1464 }
1465}
1466
1467impl Display for OutputToString {
1468 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1469 self.output.fmt(f)
1470 }
1471}