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