1use anyhow::{anyhow, bail, Result};
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 let FunctionKind::Constructor(_) = func.kind {
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 self.print_name_type(name, TypeKind::Other);
480 self.output.str(": ");
481 match item {
482 WorldItem::Interface { id, .. } => {
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_function(resolve, f)?;
491 self.output.semicolon();
492 }
493 WorldItem::Type(_) => unreachable!(),
495 }
496 }
497 WorldKey::Interface(id) => {
498 match item {
499 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
500 _ => unreachable!(),
501 }
502 self.print_path_to_interface(resolve, *id, cur_pkg)?;
503 self.output.semicolon();
504 }
505 }
506 Ok(())
507 }
508
509 fn print_path_to_interface(
510 &mut self,
511 resolve: &Resolve,
512 interface: InterfaceId,
513 cur_pkg: PackageId,
514 ) -> Result<()> {
515 let iface = &resolve.interfaces[interface];
516 if iface.package == Some(cur_pkg) {
517 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
518 } else {
519 let pkg = &resolve.packages[iface.package.unwrap()].name;
520 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
521 self.output.str(":");
522 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
523 self.output.str("/");
524 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
525 if let Some(version) = &pkg.version {
526 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
527 }
528 }
529 Ok(())
530 }
531
532 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
534 match ty {
535 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
536 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
537 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
538 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
539 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
540 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
541 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
542 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
543 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
544 Type::F32 => {
545 if self.print_f32_f64 {
546 self.output.ty("f32", TypeKind::BuiltIn)
547 } else {
548 self.output.ty("f32", TypeKind::BuiltIn)
549 }
550 }
551 Type::F64 => {
552 if self.print_f32_f64 {
553 self.output.ty("f64", TypeKind::BuiltIn)
554 } else {
555 self.output.ty("f64", TypeKind::BuiltIn)
556 }
557 }
558 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
559 Type::String => self.output.ty("string", TypeKind::BuiltIn),
560 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
561
562 Type::Id(id) => {
563 let ty = &resolve.types[*id];
564 if let Some(name) = &ty.name {
565 self.print_name_type(name, TypeKind::Other);
566 return Ok(());
567 }
568
569 match &ty.kind {
570 TypeDefKind::Handle(h) => {
571 self.print_handle_type(resolve, h, false)?;
572 }
573 TypeDefKind::Resource => {
574 bail!("resolve has an unnamed resource type");
575 }
576 TypeDefKind::Tuple(t) => {
577 self.print_tuple_type(resolve, t)?;
578 }
579 TypeDefKind::Option(t) => {
580 self.print_option_type(resolve, t)?;
581 }
582 TypeDefKind::Result(t) => {
583 self.print_result_type(resolve, t)?;
584 }
585 TypeDefKind::Record(_) => {
586 bail!("resolve has an unnamed record type");
587 }
588 TypeDefKind::Flags(_) => {
589 bail!("resolve has unnamed flags type")
590 }
591 TypeDefKind::Enum(_) => {
592 bail!("resolve has unnamed enum type")
593 }
594 TypeDefKind::Variant(_) => {
595 bail!("resolve has unnamed variant type")
596 }
597 TypeDefKind::List(ty) => {
598 self.output.ty("list", TypeKind::BuiltIn);
599 self.output.generic_args_start();
600 self.print_type_name(resolve, ty)?;
601 self.output.generic_args_end();
602 }
603 TypeDefKind::FixedSizeList(ty, size) => {
604 self.output.ty("list", TypeKind::BuiltIn);
605 self.output.generic_args_start();
606 self.print_type_name(resolve, ty)?;
607 self.output.push_str(&format!(", {}", *size));
608 self.output.generic_args_end();
609 }
610 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
611 TypeDefKind::Future(ty) => {
612 if let Some(ty) = ty {
613 self.output.push_str("future<");
614 self.print_type_name(resolve, ty)?;
615 self.output.push_str(">");
616 } else {
617 self.output.push_str("future");
618 }
619 }
620 TypeDefKind::Stream(ty) => {
621 if let Some(ty) = ty {
622 self.output.push_str("stream<");
623 self.print_type_name(resolve, ty)?;
624 self.output.push_str(">");
625 } else {
626 self.output.push_str("stream");
627 }
628 }
629 TypeDefKind::Unknown => unreachable!(),
630 }
631 }
632 }
633
634 Ok(())
635 }
636
637 fn print_handle_type(
638 &mut self,
639 resolve: &Resolve,
640 handle: &Handle,
641 force_handle_type_printed: bool,
642 ) -> Result<()> {
643 match handle {
644 Handle::Own(ty) => {
645 let ty = &resolve.types[*ty];
646 if force_handle_type_printed {
647 self.output.ty("own", TypeKind::BuiltIn);
648 self.output.generic_args_start();
649 }
650 self.print_name_type(
651 ty.name
652 .as_ref()
653 .ok_or_else(|| anyhow!("unnamed resource type"))?,
654 TypeKind::Resource,
655 );
656 if force_handle_type_printed {
657 self.output.generic_args_end();
658 }
659 }
660
661 Handle::Borrow(ty) => {
662 self.output.ty("borrow", TypeKind::BuiltIn);
663 self.output.generic_args_start();
664 let ty = &resolve.types[*ty];
665 self.print_name_type(
666 ty.name
667 .as_ref()
668 .ok_or_else(|| anyhow!("unnamed resource type"))?,
669 TypeKind::Resource,
670 );
671 self.output.generic_args_end();
672 }
673 }
674
675 Ok(())
676 }
677
678 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
679 self.output.ty("tuple", TypeKind::BuiltIn);
680 self.output.generic_args_start();
681 for (i, ty) in tuple.types.iter().enumerate() {
682 if i > 0 {
683 self.output.str(", ");
684 }
685 self.print_type_name(resolve, ty)?;
686 }
687 self.output.generic_args_end();
688
689 Ok(())
690 }
691
692 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
693 self.output.ty("option", TypeKind::BuiltIn);
694 self.output.generic_args_start();
695 self.print_type_name(resolve, payload)?;
696 self.output.generic_args_end();
697 Ok(())
698 }
699
700 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
701 match result {
702 Result_ {
703 ok: Some(ok),
704 err: Some(err),
705 } => {
706 self.output.ty("result", TypeKind::BuiltIn);
707 self.output.generic_args_start();
708 self.print_type_name(resolve, ok)?;
709 self.output.str(", ");
710 self.print_type_name(resolve, err)?;
711 self.output.generic_args_end();
712 }
713 Result_ {
714 ok: None,
715 err: Some(err),
716 } => {
717 self.output.ty("result", TypeKind::BuiltIn);
718 self.output.generic_args_start();
719 self.output.str("_, ");
720 self.print_type_name(resolve, err)?;
721 self.output.generic_args_end();
722 }
723 Result_ {
724 ok: Some(ok),
725 err: None,
726 } => {
727 self.output.ty("result", TypeKind::BuiltIn);
728 self.output.generic_args_start();
729 self.print_type_name(resolve, ok)?;
730 self.output.generic_args_end();
731 }
732 Result_ {
733 ok: None,
734 err: None,
735 } => {
736 self.output.ty("result", TypeKind::BuiltIn);
737 }
738 }
739 Ok(())
740 }
741
742 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
743 match ty {
744 Type::Bool
745 | Type::U8
746 | Type::U16
747 | Type::U32
748 | Type::U64
749 | Type::S8
750 | Type::S16
751 | Type::S32
752 | Type::S64
753 | Type::F32
754 | Type::F64
755 | Type::Char
756 | Type::String
757 | Type::ErrorContext => return Ok(()),
758
759 Type::Id(id) => {
760 let ty = &resolve.types[*id];
761 match &ty.kind {
762 TypeDefKind::Handle(h) => {
763 self.declare_handle(resolve, ty.name.as_deref(), h)?
764 }
765 TypeDefKind::Resource => panic!("resources should be processed separately"),
766 TypeDefKind::Record(r) => {
767 self.declare_record(resolve, ty.name.as_deref(), r)?
768 }
769 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
770 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
771 TypeDefKind::Variant(v) => {
772 self.declare_variant(resolve, ty.name.as_deref(), v)?
773 }
774 TypeDefKind::Option(t) => {
775 self.declare_option(resolve, ty.name.as_deref(), t)?
776 }
777 TypeDefKind::Result(r) => {
778 self.declare_result(resolve, ty.name.as_deref(), r)?
779 }
780 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
781 TypeDefKind::List(inner) => {
782 self.declare_list(resolve, ty.name.as_deref(), inner)?
783 }
784 TypeDefKind::FixedSizeList(inner, size) => {
785 self.declare_fixed_size_list(resolve, ty.name.as_deref(), inner, *size)?
786 }
787 TypeDefKind::Type(inner) => match ty.name.as_deref() {
788 Some(name) => {
789 self.output.keyword("type");
790 self.output.str(" ");
791 self.print_name_type(name, TypeKind::TypeName);
792 self.output.str(" = ");
793 self.print_type_name(resolve, inner)?;
794 self.output.semicolon();
795 }
796 None => bail!("unnamed type in document"),
797 },
798 TypeDefKind::Future(inner) => {
799 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
800 }
801 TypeDefKind::Stream(inner) => {
802 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
803 }
804 TypeDefKind::Unknown => unreachable!(),
805 }
806 }
807 }
808 Ok(())
809 }
810
811 fn declare_handle(
812 &mut self,
813 resolve: &Resolve,
814 name: Option<&str>,
815 handle: &Handle,
816 ) -> Result<()> {
817 match name {
818 Some(name) => {
819 self.output.keyword("type");
820 self.output.str(" ");
821 self.print_name_type(name, TypeKind::Resource);
822 self.output.str(" = ");
823 self.print_handle_type(resolve, handle, true)?;
829 self.output.semicolon();
830
831 Ok(())
832 }
833 None => bail!("document has unnamed handle type"),
834 }
835 }
836
837 fn declare_record(
838 &mut self,
839 resolve: &Resolve,
840 name: Option<&str>,
841 record: &Record,
842 ) -> Result<()> {
843 match name {
844 Some(name) => {
845 self.output.keyword("record");
846 self.output.str(" ");
847 self.print_name_type(name, TypeKind::Record);
848 self.output.indent_start();
849 for field in &record.fields {
850 self.print_docs(&field.docs);
851 self.print_name_param(&field.name);
852 self.output.str(": ");
853 self.print_type_name(resolve, &field.ty)?;
854 self.output.str(",");
855 self.output.newline();
856 }
857 self.output.indent_end();
858 Ok(())
859 }
860 None => bail!("document has unnamed record type"),
861 }
862 }
863
864 fn declare_tuple(
865 &mut self,
866 resolve: &Resolve,
867 name: Option<&str>,
868 tuple: &Tuple,
869 ) -> Result<()> {
870 if let Some(name) = name {
871 self.output.keyword("type");
872 self.output.str(" ");
873 self.print_name_type(name, TypeKind::Tuple);
874 self.output.str(" = ");
875 self.print_tuple_type(resolve, tuple)?;
876 self.output.semicolon();
877 }
878 Ok(())
879 }
880
881 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
882 match name {
883 Some(name) => {
884 self.output.keyword("flags");
885 self.output.str(" ");
886 self.print_name_type(name, TypeKind::Flags);
887 self.output.indent_start();
888 for flag in &flags.flags {
889 self.print_docs(&flag.docs);
890 self.print_name_case(&flag.name);
891 self.output.str(",");
892 self.output.newline();
893 }
894 self.output.indent_end();
895 }
896 None => bail!("document has unnamed flags type"),
897 }
898 Ok(())
899 }
900
901 fn declare_variant(
902 &mut self,
903 resolve: &Resolve,
904 name: Option<&str>,
905 variant: &Variant,
906 ) -> Result<()> {
907 let name = match name {
908 Some(name) => name,
909 None => bail!("document has unnamed variant type"),
910 };
911 self.output.keyword("variant");
912 self.output.str(" ");
913 self.print_name_type(name, TypeKind::Variant);
914 self.output.indent_start();
915 for case in &variant.cases {
916 self.print_docs(&case.docs);
917 self.print_name_case(&case.name);
918 if let Some(ty) = case.ty {
919 self.output.str("(");
920 self.print_type_name(resolve, &ty)?;
921 self.output.str(")");
922 }
923 self.output.str(",");
924 self.output.newline();
925 }
926 self.output.indent_end();
927 Ok(())
928 }
929
930 fn declare_option(
931 &mut self,
932 resolve: &Resolve,
933 name: Option<&str>,
934 payload: &Type,
935 ) -> Result<()> {
936 if let Some(name) = name {
937 self.output.keyword("type");
938 self.output.str(" ");
939 self.print_name_type(name, TypeKind::Option);
940 self.output.str(" = ");
941 self.print_option_type(resolve, payload)?;
942 self.output.semicolon();
943 }
944 Ok(())
945 }
946
947 fn declare_result(
948 &mut self,
949 resolve: &Resolve,
950 name: Option<&str>,
951 result: &Result_,
952 ) -> Result<()> {
953 if let Some(name) = name {
954 self.output.keyword("type");
955 self.output.str(" ");
956 self.print_name_type(name, TypeKind::Result);
957 self.output.str(" = ");
958 self.print_result_type(resolve, result)?;
959 self.output.semicolon();
960 }
961 Ok(())
962 }
963
964 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
965 let name = match name {
966 Some(name) => name,
967 None => bail!("document has unnamed enum type"),
968 };
969 self.output.keyword("enum");
970 self.output.str(" ");
971 self.print_name_type(name, TypeKind::Enum);
972 self.output.indent_start();
973 for case in &enum_.cases {
974 self.print_docs(&case.docs);
975 self.print_name_case(&case.name);
976 self.output.str(",");
977 self.output.newline();
978 }
979 self.output.indent_end();
980 Ok(())
981 }
982
983 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
984 if let Some(name) = name {
985 self.output.keyword("type");
986 self.output.str(" ");
987 self.print_name_type(name, TypeKind::List);
988 self.output.str(" = ");
989 self.output.ty("list", TypeKind::BuiltIn);
990 self.output.str("<");
991 self.print_type_name(resolve, ty)?;
992 self.output.str(">");
993 self.output.semicolon();
994 return Ok(());
995 }
996
997 Ok(())
998 }
999
1000 fn declare_fixed_size_list(
1001 &mut self,
1002 resolve: &Resolve,
1003 name: Option<&str>,
1004 ty: &Type,
1005 elements: u32,
1006 ) -> Result<()> {
1007 if let Some(name) = name {
1008 self.output.keyword("type");
1009 self.output.str(" ");
1010 self.print_name_type(name, TypeKind::List);
1011 self.output.str(" = ");
1012 self.output.ty("list", TypeKind::BuiltIn);
1013 self.output.str("<");
1014 self.print_type_name(resolve, ty)?;
1015 self.output.str(&format!(", {elements}"));
1016 self.output.str(">");
1017 self.output.semicolon();
1018 return Ok(());
1019 }
1020
1021 Ok(())
1022 }
1023
1024 fn declare_stream(
1025 &mut self,
1026 resolve: &Resolve,
1027 name: Option<&str>,
1028 ty: Option<&Type>,
1029 ) -> Result<()> {
1030 if let Some(name) = name {
1031 self.output.keyword("type");
1032 self.output.str(" ");
1033 self.print_name_type(name, TypeKind::Stream);
1034 self.output.str(" = ");
1035 self.output.ty("stream", TypeKind::BuiltIn);
1036 if let Some(ty) = ty {
1037 self.output.str("<");
1038 self.print_type_name(resolve, ty)?;
1039 self.output.str(">");
1040 }
1041 self.output.semicolon();
1042 }
1043
1044 Ok(())
1045 }
1046
1047 fn declare_future(
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::Future);
1057 self.output.str(" = ");
1058 self.output.ty("future", 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 escape_name(name: &str) -> Cow<str> {
1071 if is_keyword(name) {
1072 Cow::Owned(format!("%{name}"))
1073 } else {
1074 Cow::Borrowed(name)
1075 }
1076 }
1077
1078 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1079 self.output.ty(Self::escape_name(name).deref(), kind);
1080 }
1081
1082 fn print_name_param(&mut self, name: &str) {
1083 self.output.param(Self::escape_name(name).deref());
1084 }
1085
1086 fn print_name_case(&mut self, name: &str) {
1087 self.output.case(Self::escape_name(name).deref());
1088 }
1089
1090 fn print_docs(&mut self, docs: &Docs) {
1091 if self.emit_docs {
1092 if let Some(contents) = &docs.contents {
1093 for line in contents.lines() {
1094 self.output.doc(line);
1095 }
1096 }
1097 }
1098 }
1099
1100 fn print_stability(&mut self, stability: &Stability) {
1101 match stability {
1102 Stability::Unknown => {}
1103 Stability::Stable { since, deprecated } => {
1104 self.output.keyword("@since");
1105 self.output.str("(");
1106 self.output.keyword("version");
1107 self.output.str(" = ");
1108 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1109 self.output.str(")");
1110 self.output.newline();
1111 if let Some(version) = deprecated {
1112 self.output.keyword("@deprecated");
1113 self.output.str("(");
1114 self.output.keyword("version");
1115 self.output.str(" = ");
1116 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1117 self.output.str(")");
1118 self.output.newline();
1119 }
1120 }
1121 Stability::Unstable {
1122 feature,
1123 deprecated,
1124 } => {
1125 self.output.keyword("@unstable");
1126 self.output.str("(");
1127 self.output.keyword("feature");
1128 self.output.str(" = ");
1129 self.output.str(feature);
1130 self.output.str(")");
1131 self.output.newline();
1132 if let Some(version) = deprecated {
1133 self.output.keyword("@deprecated");
1134 self.output.str("(");
1135 self.output.keyword("version");
1136 self.output.str(" = ");
1137 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1138 self.output.str(")");
1139 self.output.newline();
1140 }
1141 }
1142 }
1143 }
1144}
1145
1146fn is_keyword(name: &str) -> bool {
1147 matches!(
1148 name,
1149 "use"
1150 | "type"
1151 | "func"
1152 | "u8"
1153 | "u16"
1154 | "u32"
1155 | "u64"
1156 | "s8"
1157 | "s16"
1158 | "s32"
1159 | "s64"
1160 | "f32"
1161 | "f64"
1162 | "float32"
1163 | "float64"
1164 | "char"
1165 | "resource"
1166 | "record"
1167 | "flags"
1168 | "variant"
1169 | "enum"
1170 | "bool"
1171 | "string"
1172 | "option"
1173 | "result"
1174 | "future"
1175 | "stream"
1176 | "list"
1177 | "own"
1178 | "borrow"
1179 | "_"
1180 | "as"
1181 | "from"
1182 | "static"
1183 | "interface"
1184 | "tuple"
1185 | "world"
1186 | "import"
1187 | "export"
1188 | "package"
1189 | "with"
1190 | "include"
1191 | "constructor"
1192 | "error-context"
1193 | "async"
1194 )
1195}
1196
1197pub trait Output {
1203 fn push_str(&mut self, src: &str);
1211
1212 fn indent_if_needed(&mut self) -> bool;
1218
1219 fn indent_start(&mut self);
1221
1222 fn indent_end(&mut self);
1224
1225 fn indent_and_print(&mut self, src: &str) {
1228 assert!(!src.contains('\n'));
1229 let idented = self.indent_if_needed();
1230 if idented && src.starts_with(' ') {
1231 panic!("cannot add a space at the begining of a line");
1232 }
1233 self.push_str(src);
1234 }
1235
1236 fn newline(&mut self);
1238
1239 fn keyword(&mut self, src: &str) {
1242 self.indent_and_print(src);
1243 }
1244
1245 fn ty(&mut self, src: &str, _kind: TypeKind) {
1247 self.indent_and_print(src);
1248 }
1249
1250 fn param(&mut self, src: &str) {
1252 self.indent_and_print(src);
1253 }
1254
1255 fn case(&mut self, src: &str) {
1257 self.indent_and_print(src);
1258 }
1259
1260 fn generic_args_start(&mut self) {
1262 assert!(
1263 !self.indent_if_needed(),
1264 "`generic_args_start` is never called after newline"
1265 );
1266 self.push_str("<");
1267 }
1268
1269 fn generic_args_end(&mut self) {
1271 assert!(
1272 !self.indent_if_needed(),
1273 "`generic_args_end` is never called after newline"
1274 );
1275 self.push_str(">");
1276 }
1277
1278 fn doc(&mut self, doc: &str) {
1281 assert!(!doc.contains('\n'));
1282 self.indent_if_needed();
1283 self.push_str("///");
1284 if !doc.is_empty() {
1285 self.push_str(" ");
1286 self.push_str(doc);
1287 }
1288 self.newline();
1289 }
1290
1291 fn semicolon(&mut self) {
1293 assert!(
1294 !self.indent_if_needed(),
1295 "`semicolon` is never called after newline"
1296 );
1297 self.push_str(";");
1298 self.newline();
1299 }
1300
1301 fn str(&mut self, src: &str) {
1305 self.indent_and_print(src);
1306 }
1307}
1308
1309#[non_exhaustive]
1315#[derive(Clone, Copy, Debug)]
1316pub enum TypeKind {
1317 BuiltIn,
1319 Enum,
1321 ErrorContext,
1323 Flags,
1325 FunctionFreestanding,
1328 FunctionMethod,
1330 FunctionStatic,
1332 Future,
1334 InterfaceDeclaration,
1336 InterfacePath,
1338 List,
1340 NamespaceDeclaration,
1342 NamespacePath,
1344 Option,
1346 PackageNameDeclaration,
1348 PackageNamePath,
1350 Record,
1352 Resource,
1354 Result,
1356 Stream,
1358 Tuple,
1360 TypeAlias,
1362 TypeImport,
1364 TypeName,
1366 Variant,
1368 VersionDeclaration,
1370 VersionPath,
1372 VersionAnnotation,
1374 WorldDeclaration,
1376 Other,
1378}
1379
1380#[derive(Default)]
1383pub struct OutputToString {
1384 indent: usize,
1385 output: String,
1386 needs_indent: bool,
1388}
1389
1390impl Output for OutputToString {
1391 fn push_str(&mut self, src: &str) {
1392 self.output.push_str(src);
1393 }
1394
1395 fn indent_if_needed(&mut self) -> bool {
1396 if self.needs_indent {
1397 for _ in 0..self.indent {
1398 self.output.push_str(" ");
1400 }
1401 self.needs_indent = false;
1402 true
1403 } else {
1404 false
1405 }
1406 }
1407
1408 fn indent_start(&mut self) {
1409 assert!(
1410 !self.needs_indent,
1411 "`indent_start` is never called after newline"
1412 );
1413 self.output.push_str(" {");
1414 self.indent += 1;
1415 self.newline();
1416 }
1417
1418 fn indent_end(&mut self) {
1419 self.indent = self.indent.saturating_sub(1);
1424 self.indent_if_needed();
1425 self.output.push('}');
1426 self.newline();
1427 }
1428
1429 fn newline(&mut self) {
1430 self.output.push('\n');
1431 self.needs_indent = true;
1432 }
1433}
1434
1435impl From<OutputToString> for String {
1436 fn from(output: OutputToString) -> String {
1437 output.output
1438 }
1439}
1440
1441impl Display for OutputToString {
1442 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1443 self.output.fmt(f)
1444 }
1445}