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