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<()> {
387 let prev_items = mem::replace(&mut self.any_items, false);
388 let world = &resolve.worlds[id];
389 let pkgid = world.package.unwrap();
390 let mut types = Vec::new();
391 let mut resource_funcs = HashMap::new();
392 for (name, import) in world.imports.iter() {
393 match import {
394 WorldItem::Type(t) => match name {
395 WorldKey::Name(s) => types.push((s.as_str(), *t)),
396 WorldKey::Interface(_) => unreachable!(),
397 },
398 _ => {
399 if let WorldItem::Function(f) = import {
400 if let Some(id) = f.kind.resource() {
401 resource_funcs.entry(id).or_insert(Vec::new()).push(f);
402 continue;
403 }
404 }
405 self.print_world_item(resolve, name, import, pkgid, "import")?;
406 self.any_items = true;
410 }
411 }
412 }
413 self.print_types(
414 resolve,
415 TypeOwner::World(id),
416 types.into_iter(),
417 &resource_funcs,
418 )?;
419 if !world.exports.is_empty() {
420 self.new_item();
421 }
422 for (name, export) in world.exports.iter() {
423 self.print_world_item(resolve, name, export, pkgid, "export")?;
424 }
425 self.any_items = prev_items;
426 Ok(())
427 }
428
429 fn print_world_item(
430 &mut self,
431 resolve: &Resolve,
432 name: &WorldKey,
433 item: &WorldItem,
434 cur_pkg: PackageId,
435 import_or_export_keyword: &str,
436 ) -> Result<()> {
437 if matches!(name, WorldKey::Name(_)) {
439 self.print_docs(match item {
440 WorldItem::Interface { id, .. } => &resolve.interfaces[*id].docs,
441 WorldItem::Function(f) => &f.docs,
442 WorldItem::Type(_) => unreachable!(),
444 });
445 }
446
447 self.print_stability(item.stability(resolve));
448 self.output.keyword(import_or_export_keyword);
449 self.output.str(" ");
450 match name {
451 WorldKey::Name(name) => {
452 self.print_name_type(name, TypeKind::Other);
453 self.output.str(": ");
454 match item {
455 WorldItem::Interface { id, .. } => {
456 assert!(resolve.interfaces[*id].name.is_none());
457 self.output.keyword("interface");
458 self.output.indent_start();
459 self.print_interface(resolve, *id)?;
460 self.output.indent_end();
461 }
462 WorldItem::Function(f) => {
463 self.print_function(resolve, f)?;
464 self.output.semicolon();
465 }
466 WorldItem::Type(_) => unreachable!(),
468 }
469 }
470 WorldKey::Interface(id) => {
471 match item {
472 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
473 _ => unreachable!(),
474 }
475 self.print_path_to_interface(resolve, *id, cur_pkg)?;
476 self.output.semicolon();
477 }
478 }
479 Ok(())
480 }
481
482 fn print_path_to_interface(
483 &mut self,
484 resolve: &Resolve,
485 interface: InterfaceId,
486 cur_pkg: PackageId,
487 ) -> Result<()> {
488 let iface = &resolve.interfaces[interface];
489 if iface.package == Some(cur_pkg) {
490 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
491 } else {
492 let pkg = &resolve.packages[iface.package.unwrap()].name;
493 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
494 self.output.str(":");
495 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
496 self.output.str("/");
497 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
498 if let Some(version) = &pkg.version {
499 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
500 }
501 }
502 Ok(())
503 }
504
505 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
507 match ty {
508 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
509 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
510 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
511 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
512 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
513 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
514 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
515 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
516 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
517 Type::F32 => {
518 if self.print_f32_f64 {
519 self.output.ty("f32", TypeKind::BuiltIn)
520 } else {
521 self.output.ty("f32", TypeKind::BuiltIn)
522 }
523 }
524 Type::F64 => {
525 if self.print_f32_f64 {
526 self.output.ty("f64", TypeKind::BuiltIn)
527 } else {
528 self.output.ty("f64", TypeKind::BuiltIn)
529 }
530 }
531 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
532 Type::String => self.output.ty("string", TypeKind::BuiltIn),
533 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
534
535 Type::Id(id) => {
536 let ty = &resolve.types[*id];
537 if let Some(name) = &ty.name {
538 self.print_name_type(name, TypeKind::Other);
539 return Ok(());
540 }
541
542 match &ty.kind {
543 TypeDefKind::Handle(h) => {
544 self.print_handle_type(resolve, h, false)?;
545 }
546 TypeDefKind::Resource => {
547 bail!("resolve has an unnamed resource type");
548 }
549 TypeDefKind::Tuple(t) => {
550 self.print_tuple_type(resolve, t)?;
551 }
552 TypeDefKind::Option(t) => {
553 self.print_option_type(resolve, t)?;
554 }
555 TypeDefKind::Result(t) => {
556 self.print_result_type(resolve, t)?;
557 }
558 TypeDefKind::Record(_) => {
559 bail!("resolve has an unnamed record type");
560 }
561 TypeDefKind::Flags(_) => {
562 bail!("resolve has unnamed flags type")
563 }
564 TypeDefKind::Enum(_) => {
565 bail!("resolve has unnamed enum type")
566 }
567 TypeDefKind::Variant(_) => {
568 bail!("resolve has unnamed variant type")
569 }
570 TypeDefKind::List(ty) => {
571 self.output.ty("list", TypeKind::BuiltIn);
572 self.output.generic_args_start();
573 self.print_type_name(resolve, ty)?;
574 self.output.generic_args_end();
575 }
576 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
577 TypeDefKind::Future(ty) => {
578 if let Some(ty) = ty {
579 self.output.push_str("future<");
580 self.print_type_name(resolve, ty)?;
581 self.output.push_str(">");
582 } else {
583 self.output.push_str("future");
584 }
585 }
586 TypeDefKind::Stream(ty) => {
587 if let Some(ty) = ty {
588 self.output.push_str("stream<");
589 self.print_type_name(resolve, ty)?;
590 self.output.push_str(">");
591 } else {
592 self.output.push_str("stream");
593 }
594 }
595 TypeDefKind::Unknown => unreachable!(),
596 }
597 }
598 }
599
600 Ok(())
601 }
602
603 fn print_handle_type(
604 &mut self,
605 resolve: &Resolve,
606 handle: &Handle,
607 force_handle_type_printed: bool,
608 ) -> Result<()> {
609 match handle {
610 Handle::Own(ty) => {
611 let ty = &resolve.types[*ty];
612 if force_handle_type_printed {
613 self.output.ty("own", TypeKind::BuiltIn);
614 self.output.generic_args_start();
615 }
616 self.print_name_type(
617 ty.name
618 .as_ref()
619 .ok_or_else(|| anyhow!("unnamed resource type"))?,
620 TypeKind::Resource,
621 );
622 if force_handle_type_printed {
623 self.output.generic_args_end();
624 }
625 }
626
627 Handle::Borrow(ty) => {
628 self.output.ty("borrow", TypeKind::BuiltIn);
629 self.output.generic_args_start();
630 let ty = &resolve.types[*ty];
631 self.print_name_type(
632 ty.name
633 .as_ref()
634 .ok_or_else(|| anyhow!("unnamed resource type"))?,
635 TypeKind::Resource,
636 );
637 self.output.generic_args_end();
638 }
639 }
640
641 Ok(())
642 }
643
644 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
645 self.output.ty("tuple", TypeKind::BuiltIn);
646 self.output.generic_args_start();
647 for (i, ty) in tuple.types.iter().enumerate() {
648 if i > 0 {
649 self.output.str(", ");
650 }
651 self.print_type_name(resolve, ty)?;
652 }
653 self.output.generic_args_end();
654
655 Ok(())
656 }
657
658 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
659 self.output.ty("option", TypeKind::BuiltIn);
660 self.output.generic_args_start();
661 self.print_type_name(resolve, payload)?;
662 self.output.generic_args_end();
663 Ok(())
664 }
665
666 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
667 match result {
668 Result_ {
669 ok: Some(ok),
670 err: Some(err),
671 } => {
672 self.output.ty("result", TypeKind::BuiltIn);
673 self.output.generic_args_start();
674 self.print_type_name(resolve, ok)?;
675 self.output.str(", ");
676 self.print_type_name(resolve, err)?;
677 self.output.generic_args_end();
678 }
679 Result_ {
680 ok: None,
681 err: Some(err),
682 } => {
683 self.output.ty("result", TypeKind::BuiltIn);
684 self.output.generic_args_start();
685 self.output.str("_, ");
686 self.print_type_name(resolve, err)?;
687 self.output.generic_args_end();
688 }
689 Result_ {
690 ok: Some(ok),
691 err: None,
692 } => {
693 self.output.ty("result", TypeKind::BuiltIn);
694 self.output.generic_args_start();
695 self.print_type_name(resolve, ok)?;
696 self.output.generic_args_end();
697 }
698 Result_ {
699 ok: None,
700 err: None,
701 } => {
702 self.output.ty("result", TypeKind::BuiltIn);
703 }
704 }
705 Ok(())
706 }
707
708 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
709 match ty {
710 Type::Bool
711 | Type::U8
712 | Type::U16
713 | Type::U32
714 | Type::U64
715 | Type::S8
716 | Type::S16
717 | Type::S32
718 | Type::S64
719 | Type::F32
720 | Type::F64
721 | Type::Char
722 | Type::String
723 | Type::ErrorContext => return Ok(()),
724
725 Type::Id(id) => {
726 let ty = &resolve.types[*id];
727 match &ty.kind {
728 TypeDefKind::Handle(h) => {
729 self.declare_handle(resolve, ty.name.as_deref(), h)?
730 }
731 TypeDefKind::Resource => panic!("resources should be processed separately"),
732 TypeDefKind::Record(r) => {
733 self.declare_record(resolve, ty.name.as_deref(), r)?
734 }
735 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
736 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
737 TypeDefKind::Variant(v) => {
738 self.declare_variant(resolve, ty.name.as_deref(), v)?
739 }
740 TypeDefKind::Option(t) => {
741 self.declare_option(resolve, ty.name.as_deref(), t)?
742 }
743 TypeDefKind::Result(r) => {
744 self.declare_result(resolve, ty.name.as_deref(), r)?
745 }
746 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
747 TypeDefKind::List(inner) => {
748 self.declare_list(resolve, ty.name.as_deref(), inner)?
749 }
750 TypeDefKind::Type(inner) => match ty.name.as_deref() {
751 Some(name) => {
752 self.output.keyword("type");
753 self.output.str(" ");
754 self.print_name_type(name, TypeKind::TypeName);
755 self.output.str(" = ");
756 self.print_type_name(resolve, inner)?;
757 self.output.semicolon();
758 }
759 None => bail!("unnamed type in document"),
760 },
761 TypeDefKind::Future(inner) => {
762 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
763 }
764 TypeDefKind::Stream(inner) => {
765 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
766 }
767 TypeDefKind::Unknown => unreachable!(),
768 }
769 }
770 }
771 Ok(())
772 }
773
774 fn declare_handle(
775 &mut self,
776 resolve: &Resolve,
777 name: Option<&str>,
778 handle: &Handle,
779 ) -> Result<()> {
780 match name {
781 Some(name) => {
782 self.output.keyword("type");
783 self.output.str(" ");
784 self.print_name_type(name, TypeKind::Resource);
785 self.output.str(" = ");
786 self.print_handle_type(resolve, handle, true)?;
792 self.output.semicolon();
793
794 Ok(())
795 }
796 None => bail!("document has unnamed handle type"),
797 }
798 }
799
800 fn declare_record(
801 &mut self,
802 resolve: &Resolve,
803 name: Option<&str>,
804 record: &Record,
805 ) -> Result<()> {
806 match name {
807 Some(name) => {
808 self.output.keyword("record");
809 self.output.str(" ");
810 self.print_name_type(name, TypeKind::Record);
811 self.output.indent_start();
812 for field in &record.fields {
813 self.print_docs(&field.docs);
814 self.print_name_param(&field.name);
815 self.output.str(": ");
816 self.print_type_name(resolve, &field.ty)?;
817 self.output.str(",");
818 self.output.newline();
819 }
820 self.output.indent_end();
821 Ok(())
822 }
823 None => bail!("document has unnamed record type"),
824 }
825 }
826
827 fn declare_tuple(
828 &mut self,
829 resolve: &Resolve,
830 name: Option<&str>,
831 tuple: &Tuple,
832 ) -> Result<()> {
833 if let Some(name) = name {
834 self.output.keyword("type");
835 self.output.str(" ");
836 self.print_name_type(name, TypeKind::Tuple);
837 self.output.str(" = ");
838 self.print_tuple_type(resolve, tuple)?;
839 self.output.semicolon();
840 }
841 Ok(())
842 }
843
844 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
845 match name {
846 Some(name) => {
847 self.output.keyword("flags");
848 self.output.str(" ");
849 self.print_name_type(name, TypeKind::Flags);
850 self.output.indent_start();
851 for flag in &flags.flags {
852 self.print_docs(&flag.docs);
853 self.print_name_case(&flag.name);
854 self.output.str(",");
855 self.output.newline();
856 }
857 self.output.indent_end();
858 }
859 None => bail!("document has unnamed flags type"),
860 }
861 Ok(())
862 }
863
864 fn declare_variant(
865 &mut self,
866 resolve: &Resolve,
867 name: Option<&str>,
868 variant: &Variant,
869 ) -> Result<()> {
870 let name = match name {
871 Some(name) => name,
872 None => bail!("document has unnamed variant type"),
873 };
874 self.output.keyword("variant");
875 self.output.str(" ");
876 self.print_name_type(name, TypeKind::Variant);
877 self.output.indent_start();
878 for case in &variant.cases {
879 self.print_docs(&case.docs);
880 self.print_name_case(&case.name);
881 if let Some(ty) = case.ty {
882 self.output.str("(");
883 self.print_type_name(resolve, &ty)?;
884 self.output.str(")");
885 }
886 self.output.str(",");
887 self.output.newline();
888 }
889 self.output.indent_end();
890 Ok(())
891 }
892
893 fn declare_option(
894 &mut self,
895 resolve: &Resolve,
896 name: Option<&str>,
897 payload: &Type,
898 ) -> Result<()> {
899 if let Some(name) = name {
900 self.output.keyword("type");
901 self.output.str(" ");
902 self.print_name_type(name, TypeKind::Option);
903 self.output.str(" = ");
904 self.print_option_type(resolve, payload)?;
905 self.output.semicolon();
906 }
907 Ok(())
908 }
909
910 fn declare_result(
911 &mut self,
912 resolve: &Resolve,
913 name: Option<&str>,
914 result: &Result_,
915 ) -> Result<()> {
916 if let Some(name) = name {
917 self.output.keyword("type");
918 self.output.str(" ");
919 self.print_name_type(name, TypeKind::Result);
920 self.output.str(" = ");
921 self.print_result_type(resolve, result)?;
922 self.output.semicolon();
923 }
924 Ok(())
925 }
926
927 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
928 let name = match name {
929 Some(name) => name,
930 None => bail!("document has unnamed enum type"),
931 };
932 self.output.keyword("enum");
933 self.output.str(" ");
934 self.print_name_type(name, TypeKind::Enum);
935 self.output.indent_start();
936 for case in &enum_.cases {
937 self.print_docs(&case.docs);
938 self.print_name_case(&case.name);
939 self.output.str(",");
940 self.output.newline();
941 }
942 self.output.indent_end();
943 Ok(())
944 }
945
946 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
947 if let Some(name) = name {
948 self.output.keyword("type");
949 self.output.str(" ");
950 self.print_name_type(name, TypeKind::List);
951 self.output.str(" = ");
952 self.output.ty("list", TypeKind::BuiltIn);
953 self.output.str("<");
954 self.print_type_name(resolve, ty)?;
955 self.output.str(">");
956 self.output.semicolon();
957 return Ok(());
958 }
959
960 Ok(())
961 }
962
963 fn declare_stream(
964 &mut self,
965 resolve: &Resolve,
966 name: Option<&str>,
967 ty: Option<&Type>,
968 ) -> Result<()> {
969 if let Some(name) = name {
970 self.output.keyword("type");
971 self.output.str(" ");
972 self.print_name_type(name, TypeKind::Stream);
973 self.output.str(" = ");
974 self.output.ty("stream", TypeKind::BuiltIn);
975 if let Some(ty) = ty {
976 self.output.str("<");
977 self.print_type_name(resolve, ty)?;
978 self.output.str(">");
979 }
980 self.output.semicolon();
981 }
982
983 Ok(())
984 }
985
986 fn declare_future(
987 &mut self,
988 resolve: &Resolve,
989 name: Option<&str>,
990 ty: Option<&Type>,
991 ) -> Result<()> {
992 if let Some(name) = name {
993 self.output.keyword("type");
994 self.output.str(" ");
995 self.print_name_type(name, TypeKind::Future);
996 self.output.str(" = ");
997 self.output.ty("future", TypeKind::BuiltIn);
998 if let Some(ty) = ty {
999 self.output.str("<");
1000 self.print_type_name(resolve, ty)?;
1001 self.output.str(">");
1002 }
1003 self.output.semicolon();
1004 }
1005
1006 Ok(())
1007 }
1008
1009 fn escape_name(name: &str) -> Cow<str> {
1010 if is_keyword(name) {
1011 Cow::Owned(format!("%{name}"))
1012 } else {
1013 Cow::Borrowed(name)
1014 }
1015 }
1016
1017 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1018 self.output.ty(Self::escape_name(name).deref(), kind);
1019 }
1020
1021 fn print_name_param(&mut self, name: &str) {
1022 self.output.param(Self::escape_name(name).deref());
1023 }
1024
1025 fn print_name_case(&mut self, name: &str) {
1026 self.output.case(Self::escape_name(name).deref());
1027 }
1028
1029 fn print_docs(&mut self, docs: &Docs) {
1030 if self.emit_docs {
1031 if let Some(contents) = &docs.contents {
1032 for line in contents.lines() {
1033 self.output.doc(line);
1034 }
1035 }
1036 }
1037 }
1038
1039 fn print_stability(&mut self, stability: &Stability) {
1040 match stability {
1041 Stability::Unknown => {}
1042 Stability::Stable { since, deprecated } => {
1043 self.output.keyword("@since");
1044 self.output.str("(");
1045 self.output.keyword("version");
1046 self.output.str(" = ");
1047 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1048 self.output.str(")");
1049 self.output.newline();
1050 if let Some(version) = deprecated {
1051 self.output.keyword("@deprecated");
1052 self.output.str("(");
1053 self.output.keyword("version");
1054 self.output.str(" = ");
1055 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1056 self.output.str(")");
1057 self.output.newline();
1058 }
1059 }
1060 Stability::Unstable {
1061 feature,
1062 deprecated,
1063 } => {
1064 self.output.keyword("@unstable");
1065 self.output.str("(");
1066 self.output.keyword("feature");
1067 self.output.str(" = ");
1068 self.output.str(feature);
1069 self.output.str(")");
1070 self.output.newline();
1071 if let Some(version) = deprecated {
1072 self.output.keyword("@deprecated");
1073 self.output.str("(");
1074 self.output.keyword("version");
1075 self.output.str(" = ");
1076 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1077 self.output.str(")");
1078 self.output.newline();
1079 }
1080 }
1081 }
1082 }
1083}
1084
1085fn is_keyword(name: &str) -> bool {
1086 matches!(
1087 name,
1088 "use"
1089 | "type"
1090 | "func"
1091 | "u8"
1092 | "u16"
1093 | "u32"
1094 | "u64"
1095 | "s8"
1096 | "s16"
1097 | "s32"
1098 | "s64"
1099 | "f32"
1100 | "f64"
1101 | "float32"
1102 | "float64"
1103 | "char"
1104 | "resource"
1105 | "record"
1106 | "flags"
1107 | "variant"
1108 | "enum"
1109 | "bool"
1110 | "string"
1111 | "option"
1112 | "result"
1113 | "future"
1114 | "stream"
1115 | "list"
1116 | "own"
1117 | "borrow"
1118 | "_"
1119 | "as"
1120 | "from"
1121 | "static"
1122 | "interface"
1123 | "tuple"
1124 | "world"
1125 | "import"
1126 | "export"
1127 | "package"
1128 | "with"
1129 | "include"
1130 | "constructor"
1131 | "error-context"
1132 | "async"
1133 )
1134}
1135
1136pub trait Output {
1142 fn push_str(&mut self, src: &str);
1150
1151 fn indent_if_needed(&mut self) -> bool;
1157
1158 fn indent_start(&mut self);
1160
1161 fn indent_end(&mut self);
1163
1164 fn indent_and_print(&mut self, src: &str) {
1167 assert!(!src.contains('\n'));
1168 let idented = self.indent_if_needed();
1169 if idented && src.starts_with(' ') {
1170 panic!("cannot add a space at the begining of a line");
1171 }
1172 self.push_str(src);
1173 }
1174
1175 fn newline(&mut self);
1177
1178 fn keyword(&mut self, src: &str) {
1181 self.indent_and_print(src);
1182 }
1183
1184 fn ty(&mut self, src: &str, _kind: TypeKind) {
1186 self.indent_and_print(src);
1187 }
1188
1189 fn param(&mut self, src: &str) {
1191 self.indent_and_print(src);
1192 }
1193
1194 fn case(&mut self, src: &str) {
1196 self.indent_and_print(src);
1197 }
1198
1199 fn generic_args_start(&mut self) {
1201 assert!(
1202 !self.indent_if_needed(),
1203 "`generic_args_start` is never called after newline"
1204 );
1205 self.push_str("<");
1206 }
1207
1208 fn generic_args_end(&mut self) {
1210 assert!(
1211 !self.indent_if_needed(),
1212 "`generic_args_end` is never called after newline"
1213 );
1214 self.push_str(">");
1215 }
1216
1217 fn doc(&mut self, doc: &str) {
1220 assert!(!doc.contains('\n'));
1221 self.indent_if_needed();
1222 self.push_str("///");
1223 if !doc.is_empty() {
1224 self.push_str(" ");
1225 self.push_str(doc);
1226 }
1227 self.newline();
1228 }
1229
1230 fn semicolon(&mut self) {
1232 assert!(
1233 !self.indent_if_needed(),
1234 "`semicolon` is never called after newline"
1235 );
1236 self.push_str(";");
1237 self.newline();
1238 }
1239
1240 fn str(&mut self, src: &str) {
1244 self.indent_and_print(src);
1245 }
1246}
1247
1248#[non_exhaustive]
1254#[derive(Clone, Copy, Debug)]
1255pub enum TypeKind {
1256 BuiltIn,
1258 Enum,
1260 ErrorContext,
1262 Flags,
1264 FunctionFreestanding,
1267 FunctionMethod,
1269 FunctionStatic,
1271 Future,
1273 InterfaceDeclaration,
1275 InterfacePath,
1277 List,
1279 NamespaceDeclaration,
1281 NamespacePath,
1283 Option,
1285 PackageNameDeclaration,
1287 PackageNamePath,
1289 Record,
1291 Resource,
1293 Result,
1295 Stream,
1297 Tuple,
1299 TypeAlias,
1301 TypeImport,
1303 TypeName,
1305 Variant,
1307 VersionDeclaration,
1309 VersionPath,
1311 VersionAnnotation,
1313 WorldDeclaration,
1315 Other,
1317}
1318
1319#[derive(Default)]
1322pub struct OutputToString {
1323 indent: usize,
1324 output: String,
1325 needs_indent: bool,
1327}
1328
1329impl Output for OutputToString {
1330 fn push_str(&mut self, src: &str) {
1331 self.output.push_str(src);
1332 }
1333
1334 fn indent_if_needed(&mut self) -> bool {
1335 if self.needs_indent {
1336 for _ in 0..self.indent {
1337 self.output.push_str(" ");
1339 }
1340 self.needs_indent = false;
1341 true
1342 } else {
1343 false
1344 }
1345 }
1346
1347 fn indent_start(&mut self) {
1348 assert!(
1349 !self.needs_indent,
1350 "`indent_start` is never called after newline"
1351 );
1352 self.output.push_str(" {");
1353 self.indent += 1;
1354 self.newline();
1355 }
1356
1357 fn indent_end(&mut self) {
1358 self.indent = self.indent.saturating_sub(1);
1363 self.indent_if_needed();
1364 self.output.push('}');
1365 self.newline();
1366 }
1367
1368 fn newline(&mut self) {
1369 self.output.push('\n');
1370 self.needs_indent = true;
1371 }
1372}
1373
1374impl From<OutputToString> for String {
1375 fn from(output: OutputToString) -> String {
1376 output.output
1377 }
1378}
1379
1380impl Display for OutputToString {
1381 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1382 self.output.fmt(f)
1383 }
1384}