java_signatures/
display.rs

1use std::fmt::{Display, Write};
2
3use crate::{ClassType, TypeParameter};
4
5use super::{
6    BaseType, ClassSignature, FieldSignature, JavaType, MethodSignature, ReferenceType,
7    SimpleClassType, ThrowsType, TypeArgument,
8};
9
10impl<'a> Display for FieldSignature<'a> {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        render_reference_type(&self.0, f)
13    }
14}
15
16impl<'a> Display for ClassSignature<'a> {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        render_type_parameters(&self.type_params, f)?;
19        render_class_type(&self.super_class, f)?;
20        for ty in &self.super_ifaces {
21            render_class_type(ty, f)?;
22        }
23        Ok(())
24    }
25}
26
27impl<'a> Display for MethodSignature<'a> {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        render_type_parameters(&self.type_params, f)?;
30        f.write_char('(')?;
31        for ty in &self.parameters {
32            render_java_type(ty, f)?;
33        }
34        f.write_char(')')?;
35        match self.result {
36            crate::ResultType::VoidType => f.write_char('V'),
37            crate::ResultType::ValueType(ref ty) => render_java_type(ty, f),
38        }?;
39        for ty in &self.throws {
40            f.write_char('^')?;
41            match ty {
42                ThrowsType::ClassType(ref ty) => render_class_type(ty, f),
43                ThrowsType::TypeVariable(name) => render_type_variable(name, f),
44            }?;
45        }
46        Ok(())
47    }
48}
49
50fn render_type_variable(name: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51    write!(f, "T{};", name)
52}
53
54fn render_reference_type(
55    ty: &ReferenceType<'_>,
56    f: &mut std::fmt::Formatter<'_>,
57) -> std::fmt::Result {
58    match ty {
59        ReferenceType::Class(ty) => render_class_type(ty, f),
60        ReferenceType::Variable(name) => render_type_variable(name, f),
61        ReferenceType::Array(arr) => {
62            for _ in 0..arr.dimension {
63                f.write_char('[')?;
64            }
65            render_java_type(&arr.ty, f)
66        }
67    }
68}
69
70fn render_class_type(ty: &ClassType<'_>, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71    f.write_char('L')?;
72    render_simple_class_type(&ty.base, f)?;
73    for ty in &ty.nested {
74        f.write_char('.')?;
75        render_simple_class_type(ty, f)?;
76    }
77    f.write_char(';')
78}
79
80fn render_type_parameters(
81    tys: &[TypeParameter<'_>],
82    f: &mut std::fmt::Formatter<'_>,
83) -> std::fmt::Result {
84    if !tys.is_empty() {
85        f.write_char('<')?;
86        for ty in tys {
87            f.write_str(ty.name)?;
88            f.write_char(':')?;
89            if let Some(ref ty) = ty.class_bound {
90                render_reference_type(ty, f)?;
91            }
92            for ty in &ty.iface_bounds {
93                f.write_char(':')?;
94                render_reference_type(ty, f)?;
95            }
96        }
97        f.write_char('>')?;
98    }
99    Ok(())
100}
101
102fn render_java_type(ty: &JavaType<'_>, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103    match ty {
104        JavaType::Base(ty) => f.write_char(match ty {
105            BaseType::Byte => 'B',
106            BaseType::Char => 'C',
107            BaseType::Double => 'D',
108            BaseType::Float => 'F',
109            BaseType::Int => 'I',
110            BaseType::Long => 'J',
111            BaseType::Short => 'S',
112            BaseType::Boolean => 'Z',
113        }),
114        JavaType::Reference(ty) => render_reference_type(ty, f),
115    }
116}
117
118fn render_simple_class_type(
119    ty: &SimpleClassType,
120    f: &mut std::fmt::Formatter<'_>,
121) -> std::fmt::Result {
122    f.write_str(ty.name)?;
123    if !ty.type_args.is_empty() {
124        f.write_char('<')?;
125        for ty in &ty.type_args {
126            match ty {
127                TypeArgument::Unbounded => {
128                    f.write_char('*')?;
129                }
130                TypeArgument::Default(ty) => {
131                    render_reference_type(ty, f)?;
132                }
133                TypeArgument::Extends(ty) => {
134                    f.write_char('+')?;
135                    render_reference_type(ty, f)?;
136                }
137                TypeArgument::Super(ty) => {
138                    f.write_char('-')?;
139                    render_reference_type(ty, f)?;
140                }
141            }
142        }
143        f.write_char('>')?;
144    }
145    Ok(())
146}