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