1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::fmt;

use itertools::Itertools;

use crate::{
	common::{ArgumentList, Attribute, AttributeList, TypeDecl},
	decl::{Decl, FieldDecl},
	expr::{Expr, IdentExpr, NamespacedIdent, PrimaryExpr},
};

use super::Tooltip;

impl fmt::Display for TypeDecl {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.name)?;

		if let Some(ref child_ty) = self.child_ty {
			write!(f, "<{}>", child_ty)?;
		}

		Ok(())
	}
}

impl fmt::Display for Attribute {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "@{}", self.name)?;

		if let Some(ref params) = self.params {
			write!(f, "{params}")?;
		}

		Ok(())
	}
}

impl fmt::Display for AttributeList {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		let inner = self.attributes.iter().join(" ");

		write!(f, "{}", inner)
	}
}

// FIXME
impl fmt::Display for Decl {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		Tooltip::fmt(self, f)
	}
}

impl fmt::Display for FieldDecl {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		if let Some(ref attributes) = self.attributes {
			write!(f, "{} ", attributes)?;
		}
		write!(f, "{}: {}", self.name, self.ty)?;

		if let Some(sep) = &self.separator {
			write!(f, "{sep}")?;
		}

		Ok(())
	}
}

impl fmt::Display for IdentExpr {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		let mut this = self;
		while let IdentExpr::Namespaced(NamespacedIdent { namespace, ident }) = this {
			write!(f, "{namespace}::")?;
			this = ident.as_ref();
		}

		let IdentExpr::Leaf(name) = this else {
			unreachable!();
		};

		write!(f, "{name}")
	}
}

impl fmt::Display for ArgumentList {
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		write!(f, "{}", self.brace_open)?;

		let len = self.arguments.len();
		for (idx, expr) in self.arguments.iter().enumerate() {
			match expr {
				Expr::Primary(PrimaryExpr {
					expr,
					postfix: None,
				}) => match expr.as_ref() {
					Expr::Ident(ident) => write!(f, "{ident}"),
					Expr::Literal(literal) => write!(f, "{literal}"),
					_ => write!(f, "ERR"), // TODO
				},
				_ => write!(f, "ERR"), // TODO
			}?;

			if idx < len - 1 {
				write!(f, ", ")?;
			}
		}

		write!(f, "{}", self.brace_close)
	}
}