1use anyhow::{anyhow, bail, Result};
2use std::collections::HashMap;
3use std::fmt::{self, Write};
4use std::mem;
5use wit_parser::*;
6
7const PRINT_SEMICOLONS_DEFAULT: bool = true;
9const PRINT_F32_F64_DEFAULT: bool = false;
10
11pub struct WitPrinter {
13 output: Output,
14
15 any_items: bool,
18
19 emit_docs: bool,
21
22 print_semicolons: bool,
23 print_f32_f64: bool,
24}
25
26impl Default for WitPrinter {
27 fn default() -> Self {
28 Self {
29 output: Default::default(),
30 any_items: false,
31 emit_docs: true,
32 print_semicolons: match std::env::var("WIT_REQUIRE_SEMICOLONS") {
33 Ok(s) => s == "1",
34 Err(_) => PRINT_SEMICOLONS_DEFAULT,
35 },
36 print_f32_f64: match std::env::var("WIT_REQUIRE_F32_F64") {
37 Ok(s) => s == "1",
38 Err(_) => PRINT_F32_F64_DEFAULT,
39 },
40 }
41 }
42}
43
44impl WitPrinter {
45 pub fn emit_docs(&mut self, enabled: bool) -> &mut Self {
49 self.emit_docs = enabled;
50 self
51 }
52
53 pub fn print(&mut self, resolve: &Resolve, pkgid: PackageId) -> Result<String> {
55 let pkg = &resolve.packages[pkgid];
56 self.print_docs(&pkg.docs);
57 self.output.push_str("package ");
58 self.print_name(&pkg.name.namespace);
59 self.output.push_str(":");
60 self.print_name(&pkg.name.name);
61 if let Some(version) = &pkg.name.version {
62 self.output.push_str(&format!("@{version}"));
63 }
64 self.print_semicolon();
65 self.output.push_str("\n\n");
66 for (name, id) in pkg.interfaces.iter() {
67 self.print_docs(&resolve.interfaces[*id].docs);
68 self.output.push_str("interface ");
69 self.print_name(name);
70 self.output.push_str(" {\n");
71 self.print_interface(resolve, *id)?;
72 writeln!(&mut self.output, "}}\n")?;
73 }
74
75 for (name, id) in pkg.worlds.iter() {
76 self.print_docs(&resolve.worlds[*id].docs);
77 self.output.push_str("world ");
78 self.print_name(name);
79 self.output.push_str(" {\n");
80 self.print_world(resolve, *id)?;
81 writeln!(&mut self.output, "}}")?;
82 }
83
84 Ok(std::mem::take(&mut self.output).into())
85 }
86
87 fn print_semicolon(&mut self) {
88 if self.print_semicolons {
89 self.output.push_str(";");
90 }
91 }
92
93 fn new_item(&mut self) {
94 if self.any_items {
95 self.output.push_str("\n");
96 }
97 self.any_items = true;
98 }
99
100 fn print_interface(&mut self, resolve: &Resolve, id: InterfaceId) -> Result<()> {
102 let prev_items = mem::replace(&mut self.any_items, false);
103 let interface = &resolve.interfaces[id];
104
105 let mut resource_funcs = HashMap::new();
106 let mut freestanding = Vec::new();
107 for (name, func) in interface.functions.iter() {
108 if let Some(id) = resource_func(func) {
109 resource_funcs.entry(id).or_insert(Vec::new()).push(func);
110 } else {
111 freestanding.push((name, func));
112 }
113 }
114
115 self.print_types(
116 resolve,
117 TypeOwner::Interface(id),
118 interface
119 .types
120 .iter()
121 .map(|(name, id)| (name.as_str(), *id)),
122 &resource_funcs,
123 )?;
124
125 for (name, func) in freestanding {
126 self.new_item();
127 self.print_docs(&func.docs);
128 self.print_name(name);
129 self.output.push_str(": ");
130 self.print_function(resolve, func)?;
131 self.print_semicolon();
132 self.output.push_str("\n");
133 }
134
135 self.any_items = prev_items;
136
137 Ok(())
138 }
139
140 fn print_types<'a>(
141 &mut self,
142 resolve: &Resolve,
143 owner: TypeOwner,
144 types: impl Iterator<Item = (&'a str, TypeId)>,
145 resource_funcs: &HashMap<TypeId, Vec<&Function>>,
146 ) -> Result<()> {
147 let mut types_to_declare = Vec::new();
150 let mut types_to_import: Vec<(_, Vec<_>)> = Vec::new();
151 for (name, ty_id) in types {
152 let ty = &resolve.types[ty_id];
153 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
154 let other = &resolve.types[other];
155 match other.owner {
156 TypeOwner::None => {}
157 other_owner if owner != other_owner => {
158 let other_name = other
159 .name
160 .as_ref()
161 .ok_or_else(|| anyhow!("cannot import unnamed type"))?;
162 if let Some((owner, list)) = types_to_import.last_mut() {
163 if *owner == other_owner {
164 list.push((name, other_name));
165 continue;
166 }
167 }
168 types_to_import.push((other_owner, vec![(name, other_name)]));
169 continue;
170 }
171 _ => {}
172 }
173 }
174
175 types_to_declare.push(ty_id);
176 }
177
178 let my_pkg = match owner {
180 TypeOwner::Interface(id) => resolve.interfaces[id].package.unwrap(),
181 TypeOwner::World(id) => resolve.worlds[id].package.unwrap(),
182 TypeOwner::None => unreachable!(),
183 };
184 for (owner, tys) in types_to_import {
185 self.any_items = true;
186 write!(&mut self.output, "use ")?;
187 let id = match owner {
188 TypeOwner::Interface(id) => id,
189 _ => unreachable!(),
192 };
193 self.print_path_to_interface(resolve, id, my_pkg)?;
194 write!(&mut self.output, ".{{")?;
195 for (i, (my_name, other_name)) in tys.into_iter().enumerate() {
196 if i > 0 {
197 write!(&mut self.output, ", ")?;
198 }
199 if my_name == other_name {
200 self.print_name(my_name);
201 } else {
202 self.print_name(other_name);
203 self.output.push_str(" as ");
204 self.print_name(my_name);
205 }
206 }
207 write!(&mut self.output, "}}")?;
208 self.print_semicolon();
209 self.output.push_str("\n");
210 }
211
212 for id in types_to_declare {
213 self.new_item();
214 self.print_docs(&resolve.types[id].docs);
215 match resolve.types[id].kind {
216 TypeDefKind::Resource => self.print_resource(
217 resolve,
218 id,
219 resource_funcs.get(&id).unwrap_or(&Vec::new()),
220 )?,
221 _ => self.declare_type(resolve, &Type::Id(id))?,
222 }
223 }
224
225 Ok(())
226 }
227
228 fn print_resource(&mut self, resolve: &Resolve, id: TypeId, funcs: &[&Function]) -> Result<()> {
229 let ty = &resolve.types[id];
230 self.output.push_str("resource ");
231 self.print_name(ty.name.as_ref().expect("resources must be named"));
232 if funcs.is_empty() {
233 self.print_semicolon();
234 self.output.push_str("\n");
235 return Ok(());
236 }
237 self.output.push_str(" {\n");
238 for func in funcs {
239 match &func.kind {
240 FunctionKind::Constructor(_) => {
241 self.print_docs(&func.docs);
242 }
243 FunctionKind::Method(_) => {
244 self.print_docs(&func.docs);
245 self.print_name(func.item_name());
246 self.output.push_str(": ");
247 }
248 FunctionKind::Static(_) => {
249 self.print_docs(&func.docs);
250 self.print_name(func.item_name());
251 self.output.push_str(": ");
252 self.output.push_str("static ");
253 }
254 FunctionKind::Freestanding => unreachable!(),
255 }
256 self.print_function(resolve, func)?;
257 self.print_semicolon();
258 self.output.push_str("\n");
259 }
260 self.output.push_str("}\n");
261
262 Ok(())
263 }
264
265 fn print_function(&mut self, resolve: &Resolve, func: &Function) -> Result<()> {
266 match &func.kind {
268 FunctionKind::Constructor(_) => self.output.push_str("constructor("),
269 _ => self.output.push_str("func("),
270 }
271
272 let params_to_skip = match &func.kind {
274 FunctionKind::Method(_) => 1,
275 _ => 0,
276 };
277 for (i, (name, ty)) in func.params.iter().skip(params_to_skip).enumerate() {
278 if i > 0 {
279 self.output.push_str(", ");
280 }
281 self.print_name(name);
282 self.output.push_str(": ");
283 self.print_type_name(resolve, ty)?;
284 }
285 self.output.push_str(")");
286
287 if let FunctionKind::Constructor(_) = func.kind {
289 return Ok(());
290 }
291
292 match &func.results {
293 Results::Named(rs) => match rs.len() {
294 0 => (),
295 _ => {
296 self.output.push_str(" -> (");
297 for (i, (name, ty)) in rs.iter().enumerate() {
298 if i > 0 {
299 self.output.push_str(", ");
300 }
301 self.print_name(name);
302 self.output.push_str(": ");
303 self.print_type_name(resolve, ty)?;
304 }
305 self.output.push_str(")");
306 }
307 },
308 Results::Anon(ty) => {
309 self.output.push_str(" -> ");
310 self.print_type_name(resolve, ty)?;
311 }
312 }
313 Ok(())
314 }
315
316 fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
317 let prev_items = mem::replace(&mut self.any_items, false);
318 let world = &resolve.worlds[id];
319 let pkgid = world.package.unwrap();
320 let mut types = Vec::new();
321 let mut resource_funcs = HashMap::new();
322 for (name, import) in world.imports.iter() {
323 match import {
324 WorldItem::Type(t) => match name {
325 WorldKey::Name(s) => types.push((s.as_str(), *t)),
326 WorldKey::Interface(_) => unreachable!(),
327 },
328 _ => {
329 if let WorldItem::Function(f) = import {
330 if let Some(id) = resource_func(f) {
331 resource_funcs.entry(id).or_insert(Vec::new()).push(f);
332 continue;
333 }
334 }
335 self.print_world_item(resolve, name, import, pkgid, "import")?;
336 self.any_items = true;
340 }
341 }
342 }
343 self.print_types(
344 resolve,
345 TypeOwner::World(id),
346 types.into_iter(),
347 &resource_funcs,
348 )?;
349 if !world.exports.is_empty() {
350 self.new_item();
351 }
352 for (name, export) in world.exports.iter() {
353 self.print_world_item(resolve, name, export, pkgid, "export")?;
354 }
355 self.any_items = prev_items;
356 Ok(())
357 }
358
359 fn print_world_item(
360 &mut self,
361 resolve: &Resolve,
362 name: &WorldKey,
363 item: &WorldItem,
364 cur_pkg: PackageId,
365 desc: &str,
366 ) -> Result<()> {
367 if matches!(name, WorldKey::Name(_)) {
369 self.print_docs(match item {
370 WorldItem::Interface(id) => &resolve.interfaces[*id].docs,
371 WorldItem::Function(f) => &f.docs,
372 WorldItem::Type(_) => unreachable!(),
374 });
375 }
376
377 self.output.push_str(desc);
378 self.output.push_str(" ");
379 match name {
380 WorldKey::Name(name) => {
381 self.print_name(name);
382 self.output.push_str(": ");
383 match item {
384 WorldItem::Interface(id) => {
385 assert!(resolve.interfaces[*id].name.is_none());
386 writeln!(self.output, "interface {{")?;
387 self.print_interface(resolve, *id)?;
388 writeln!(self.output, "}}")?;
389 }
390 WorldItem::Function(f) => {
391 self.print_function(resolve, f)?;
392 self.print_semicolon();
393 self.output.push_str("\n");
394 }
395 WorldItem::Type(_) => unreachable!(),
397 }
398 }
399 WorldKey::Interface(id) => {
400 match item {
401 WorldItem::Interface(id2) => assert_eq!(id, id2),
402 _ => unreachable!(),
403 }
404 self.print_path_to_interface(resolve, *id, cur_pkg)?;
405 self.print_semicolon();
406 self.output.push_str("\n");
407 }
408 }
409 Ok(())
410 }
411
412 fn print_path_to_interface(
413 &mut self,
414 resolve: &Resolve,
415 interface: InterfaceId,
416 cur_pkg: PackageId,
417 ) -> Result<()> {
418 let iface = &resolve.interfaces[interface];
419 if iface.package == Some(cur_pkg) {
420 self.print_name(iface.name.as_ref().unwrap());
421 } else {
422 let pkg = &resolve.packages[iface.package.unwrap()].name;
423 self.print_name(&pkg.namespace);
424 self.output.push_str(":");
425 self.print_name(&pkg.name);
426 self.output.push_str("/");
427 self.print_name(iface.name.as_ref().unwrap());
428 if let Some(version) = &pkg.version {
429 self.output.push_str(&format!("@{version}"));
430 }
431 }
432 Ok(())
433 }
434
435 fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
436 match ty {
437 Type::Bool => self.output.push_str("bool"),
438 Type::U8 => self.output.push_str("u8"),
439 Type::U16 => self.output.push_str("u16"),
440 Type::U32 => self.output.push_str("u32"),
441 Type::U64 => self.output.push_str("u64"),
442 Type::S8 => self.output.push_str("s8"),
443 Type::S16 => self.output.push_str("s16"),
444 Type::S32 => self.output.push_str("s32"),
445 Type::S64 => self.output.push_str("s64"),
446 Type::F32 => {
447 if self.print_f32_f64 {
448 self.output.push_str("f32")
449 } else {
450 self.output.push_str("f32")
451 }
452 }
453 Type::F64 => {
454 if self.print_f32_f64 {
455 self.output.push_str("f64")
456 } else {
457 self.output.push_str("f64")
458 }
459 }
460 Type::Char => self.output.push_str("char"),
461 Type::String => self.output.push_str("string"),
462
463 Type::Id(id) => {
464 let ty = &resolve.types[*id];
465 if let Some(name) = &ty.name {
466 self.print_name(name);
467 return Ok(());
468 }
469
470 match &ty.kind {
471 TypeDefKind::Handle(h) => {
472 self.print_handle_type(resolve, h, false)?;
473 }
474 TypeDefKind::Resource => {
475 bail!("resolve has an unnamed resource type");
476 }
477 TypeDefKind::Tuple(t) => {
478 self.print_tuple_type(resolve, t)?;
479 }
480 TypeDefKind::Option(t) => {
481 self.print_option_type(resolve, t)?;
482 }
483 TypeDefKind::Result(t) => {
484 self.print_result_type(resolve, t)?;
485 }
486 TypeDefKind::Record(_) => {
487 bail!("resolve has an unnamed record type");
488 }
489 TypeDefKind::Flags(_) => {
490 bail!("resolve has unnamed flags type")
491 }
492 TypeDefKind::Enum(_) => {
493 bail!("resolve has unnamed enum type")
494 }
495 TypeDefKind::Variant(_) => {
496 bail!("resolve has unnamed variant type")
497 }
498 TypeDefKind::List(ty) => {
499 self.output.push_str("list<");
500 self.print_type_name(resolve, ty)?;
501 self.output.push_str(">");
502 }
503 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
504 TypeDefKind::Future(_) => {
505 todo!("document has an unnamed future type")
506 }
507 TypeDefKind::Stream(_) => {
508 todo!("document has an unnamed stream type")
509 }
510 TypeDefKind::Unknown => unreachable!(),
511 }
512 }
513 }
514
515 Ok(())
516 }
517
518 fn print_handle_type(
519 &mut self,
520 resolve: &Resolve,
521 handle: &Handle,
522 force_handle_type_printed: bool,
523 ) -> Result<()> {
524 match handle {
525 Handle::Own(ty) => {
526 let ty = &resolve.types[*ty];
527 if force_handle_type_printed {
528 self.output.push_str("own<");
529 }
530 self.print_name(
531 ty.name
532 .as_ref()
533 .ok_or_else(|| anyhow!("unnamed resource type"))?,
534 );
535 if force_handle_type_printed {
536 self.output.push_str(">");
537 }
538 }
539
540 Handle::Borrow(ty) => {
541 self.output.push_str("borrow<");
542 let ty = &resolve.types[*ty];
543 self.print_name(
544 ty.name
545 .as_ref()
546 .ok_or_else(|| anyhow!("unnamed resource type"))?,
547 );
548 self.output.push_str(">");
549 }
550 }
551
552 Ok(())
553 }
554
555 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
556 self.output.push_str("tuple<");
557 for (i, ty) in tuple.types.iter().enumerate() {
558 if i > 0 {
559 self.output.push_str(", ");
560 }
561 self.print_type_name(resolve, ty)?;
562 }
563 self.output.push_str(">");
564
565 Ok(())
566 }
567
568 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
569 self.output.push_str("option<");
570 self.print_type_name(resolve, payload)?;
571 self.output.push_str(">");
572 Ok(())
573 }
574
575 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
576 match result {
577 Result_ {
578 ok: Some(ok),
579 err: Some(err),
580 } => {
581 self.output.push_str("result<");
582 self.print_type_name(resolve, ok)?;
583 self.output.push_str(", ");
584 self.print_type_name(resolve, err)?;
585 self.output.push_str(">");
586 }
587 Result_ {
588 ok: None,
589 err: Some(err),
590 } => {
591 self.output.push_str("result<_, ");
592 self.print_type_name(resolve, err)?;
593 self.output.push_str(">");
594 }
595 Result_ {
596 ok: Some(ok),
597 err: None,
598 } => {
599 self.output.push_str("result<");
600 self.print_type_name(resolve, ok)?;
601 self.output.push_str(">");
602 }
603 Result_ {
604 ok: None,
605 err: None,
606 } => {
607 self.output.push_str("result");
608 }
609 }
610 Ok(())
611 }
612
613 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
614 match ty {
615 Type::Bool
616 | Type::U8
617 | Type::U16
618 | Type::U32
619 | Type::U64
620 | Type::S8
621 | Type::S16
622 | Type::S32
623 | Type::S64
624 | Type::F32
625 | Type::F64
626 | Type::Char
627 | Type::String => return Ok(()),
628
629 Type::Id(id) => {
630 let ty = &resolve.types[*id];
631 match &ty.kind {
632 TypeDefKind::Handle(h) => {
633 self.declare_handle(resolve, ty.name.as_deref(), h)?
634 }
635 TypeDefKind::Resource => panic!("resources should be processed separately"),
636 TypeDefKind::Record(r) => {
637 self.declare_record(resolve, ty.name.as_deref(), r)?
638 }
639 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
640 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
641 TypeDefKind::Variant(v) => {
642 self.declare_variant(resolve, ty.name.as_deref(), v)?
643 }
644 TypeDefKind::Option(t) => {
645 self.declare_option(resolve, ty.name.as_deref(), t)?
646 }
647 TypeDefKind::Result(r) => {
648 self.declare_result(resolve, ty.name.as_deref(), r)?
649 }
650 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
651 TypeDefKind::List(inner) => {
652 self.declare_list(resolve, ty.name.as_deref(), inner)?
653 }
654 TypeDefKind::Type(inner) => match ty.name.as_deref() {
655 Some(name) => {
656 self.output.push_str("type ");
657 self.print_name(name);
658 self.output.push_str(" = ");
659 self.print_type_name(resolve, inner)?;
660 self.print_semicolon();
661 self.output.push_str("\n");
662 }
663 None => bail!("unnamed type in document"),
664 },
665 TypeDefKind::Future(_) => todo!("declare future"),
666 TypeDefKind::Stream(_) => todo!("declare stream"),
667 TypeDefKind::Unknown => unreachable!(),
668 }
669 }
670 }
671 Ok(())
672 }
673
674 fn declare_handle(
675 &mut self,
676 resolve: &Resolve,
677 name: Option<&str>,
678 handle: &Handle,
679 ) -> Result<()> {
680 match name {
681 Some(name) => {
682 self.output.push_str("type ");
683 self.print_name(name);
684 self.output.push_str(" = ");
685 self.print_handle_type(resolve, handle, true)?;
691 self.print_semicolon();
692 self.output.push_str("\n");
693
694 Ok(())
695 }
696 None => bail!("document has unnamed handle type"),
697 }
698 }
699
700 fn declare_record(
701 &mut self,
702 resolve: &Resolve,
703 name: Option<&str>,
704 record: &Record,
705 ) -> Result<()> {
706 match name {
707 Some(name) => {
708 self.output.push_str("record ");
709 self.print_name(name);
710 self.output.push_str(" {\n");
711 for field in &record.fields {
712 self.print_docs(&field.docs);
713 self.print_name(&field.name);
714 self.output.push_str(": ");
715 self.print_type_name(resolve, &field.ty)?;
716 self.output.push_str(",\n");
717 }
718 self.output.push_str("}\n");
719 Ok(())
720 }
721 None => bail!("document has unnamed record type"),
722 }
723 }
724
725 fn declare_tuple(
726 &mut self,
727 resolve: &Resolve,
728 name: Option<&str>,
729 tuple: &Tuple,
730 ) -> Result<()> {
731 if let Some(name) = name {
732 self.output.push_str("type ");
733 self.print_name(name);
734 self.output.push_str(" = ");
735 self.print_tuple_type(resolve, tuple)?;
736 self.print_semicolon();
737 self.output.push_str("\n");
738 }
739 Ok(())
740 }
741
742 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
743 match name {
744 Some(name) => {
745 self.output.push_str("flags ");
746 self.print_name(name);
747 self.output.push_str(" {\n");
748 for flag in &flags.flags {
749 self.print_docs(&flag.docs);
750 self.print_name(&flag.name);
751 self.output.push_str(",\n");
752 }
753 self.output.push_str("}\n");
754 }
755 None => bail!("document has unnamed flags type"),
756 }
757 Ok(())
758 }
759
760 fn declare_variant(
761 &mut self,
762 resolve: &Resolve,
763 name: Option<&str>,
764 variant: &Variant,
765 ) -> Result<()> {
766 let name = match name {
767 Some(name) => name,
768 None => bail!("document has unnamed variant type"),
769 };
770 self.output.push_str("variant ");
771 self.print_name(name);
772 self.output.push_str(" {\n");
773 for case in &variant.cases {
774 self.print_docs(&case.docs);
775 self.print_name(&case.name);
776 if let Some(ty) = case.ty {
777 self.output.push_str("(");
778 self.print_type_name(resolve, &ty)?;
779 self.output.push_str(")");
780 }
781 self.output.push_str(",\n");
782 }
783 self.output.push_str("}\n");
784 Ok(())
785 }
786
787 fn declare_option(
788 &mut self,
789 resolve: &Resolve,
790 name: Option<&str>,
791 payload: &Type,
792 ) -> Result<()> {
793 if let Some(name) = name {
794 self.output.push_str("type ");
795 self.print_name(name);
796 self.output.push_str(" = ");
797 self.print_option_type(resolve, payload)?;
798 self.print_semicolon();
799 self.output.push_str("\n");
800 }
801 Ok(())
802 }
803
804 fn declare_result(
805 &mut self,
806 resolve: &Resolve,
807 name: Option<&str>,
808 result: &Result_,
809 ) -> Result<()> {
810 if let Some(name) = name {
811 self.output.push_str("type ");
812 self.print_name(name);
813 self.output.push_str(" = ");
814 self.print_result_type(resolve, result)?;
815 self.print_semicolon();
816 self.output.push_str("\n");
817 }
818 Ok(())
819 }
820
821 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
822 let name = match name {
823 Some(name) => name,
824 None => bail!("document has unnamed enum type"),
825 };
826 self.output.push_str("enum ");
827 self.print_name(name);
828 self.output.push_str(" {\n");
829 for case in &enum_.cases {
830 self.print_docs(&case.docs);
831 self.print_name(&case.name);
832 self.output.push_str(",\n");
833 }
834 self.output.push_str("}\n");
835 Ok(())
836 }
837
838 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
839 if let Some(name) = name {
840 self.output.push_str("type ");
841 self.print_name(name);
842 self.output.push_str(" = list<");
843 self.print_type_name(resolve, ty)?;
844 self.output.push_str(">");
845 self.print_semicolon();
846 self.output.push_str("\n");
847 return Ok(());
848 }
849
850 Ok(())
851 }
852
853 fn print_name(&mut self, name: &str) {
854 if is_keyword(name) {
855 self.output.push_str("%");
856 }
857 self.output.push_str(name);
858 }
859
860 fn print_docs(&mut self, docs: &Docs) {
861 if self.emit_docs {
862 if let Some(contents) = &docs.contents {
863 for line in contents.lines() {
864 self.output.push_str("/// ");
865 self.output.push_str(line);
866 self.output.push_str("\n");
867 }
868 }
869 }
870 }
871}
872
873fn resource_func(f: &Function) -> Option<TypeId> {
874 match f.kind {
875 FunctionKind::Freestanding => None,
876 FunctionKind::Method(id) | FunctionKind::Constructor(id) | FunctionKind::Static(id) => {
877 Some(id)
878 }
879 }
880}
881
882fn is_keyword(name: &str) -> bool {
883 matches!(
884 name,
885 "use"
886 | "type"
887 | "func"
888 | "u8"
889 | "u16"
890 | "u32"
891 | "u64"
892 | "s8"
893 | "s16"
894 | "s32"
895 | "s64"
896 | "f32"
897 | "f64"
898 | "float32"
899 | "float64"
900 | "char"
901 | "resource"
902 | "record"
903 | "flags"
904 | "variant"
905 | "enum"
906 | "bool"
907 | "string"
908 | "option"
909 | "result"
910 | "future"
911 | "stream"
912 | "list"
913 | "own"
914 | "borrow"
915 | "_"
916 | "as"
917 | "from"
918 | "static"
919 | "interface"
920 | "tuple"
921 | "world"
922 | "import"
923 | "export"
924 | "package"
925 | "with"
926 | "include"
927 | "constructor"
928 )
929}
930
931#[derive(Default)]
934struct Output {
935 indent: usize,
936 output: String,
937}
938
939impl Output {
940 fn push_str(&mut self, src: &str) {
941 let lines = src.lines().collect::<Vec<_>>();
942 for (i, line) in lines.iter().enumerate() {
943 let trimmed = line.trim();
944 if trimmed.starts_with('}') && self.output.ends_with(" ") {
945 self.output.pop();
946 self.output.pop();
947 }
948 self.output.push_str(if lines.len() == 1 {
949 line
950 } else {
951 line.trim_start()
952 });
953 if trimmed.ends_with('{') {
954 self.indent += 1;
955 }
956 if trimmed.starts_with('}') {
957 self.indent = self.indent.saturating_sub(1);
962 }
963 if i != lines.len() - 1 || src.ends_with('\n') {
964 while let Some(c) = self.output.chars().next_back() {
967 if c.is_whitespace() && c != '\n' {
968 self.output.pop();
969 } else {
970 break;
971 }
972 }
973 self.output.push('\n');
974 for _ in 0..self.indent {
975 self.output.push_str(" ");
976 }
977 }
978 }
979 }
980}
981
982impl Write for Output {
983 fn write_str(&mut self, s: &str) -> fmt::Result {
984 self.push_str(s);
985 Ok(())
986 }
987}
988
989impl From<Output> for String {
990 fn from(output: Output) -> String {
991 output.output
992 }
993}