1use crate::error::SignatureErr;
2use crate::jtype::{JavaType, ReturnType};
3use std::fmt;
4use std::fmt::Formatter;
5use std::iter::Peekable;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct MethodSignature {
9 pub type_params: Vec<FormalTypeParam>,
10 pub params: Vec<JavaType>,
11 pub ret: ReturnType,
12 pub throws: Vec<JavaType>,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct ClassSignature {
17 pub type_params: Vec<FormalTypeParam>,
18 pub super_class: JavaType,
19 pub interfaces: Vec<JavaType>,
20 pub is_interface: bool,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct FormalTypeParam {
25 pub name: String,
26 pub class_bound: Option<JavaType>,
27 pub interface_bounds: Vec<JavaType>,
28}
29
30impl TryFrom<&str> for MethodSignature {
31 type Error = SignatureErr;
32
33 fn try_from(s: &str) -> Result<Self, Self::Error> {
34 let mut it = s.chars().peekable();
35
36 let type_params = if it.peek() == Some(&'<') {
37 it.next(); parse_formal_type_params(&mut it)?
39 } else {
40 Vec::new()
41 };
42
43 if it.next() != Some('(') {
44 return Err(SignatureErr::MissingParamsOpenParen);
45 }
46 let mut params = Vec::new();
47 loop {
48 match it.peek().copied() {
49 Some(')') => {
50 it.next();
51 break;
52 }
53 Some(_) => params.push(JavaType::try_recursive(&mut it)?),
54 None => return Err(SignatureErr::MissingParamsCloseParen),
55 }
56 }
57
58 let ret = ReturnType::try_recursive(&mut it)?;
59
60 let mut throws = Vec::new();
61 while it.peek() == Some(&'^') {
62 it.next();
63 let t = JavaType::try_recursive(&mut it)?;
64 throws.push(t);
65 }
66
67 if it.next().is_some() {
68 return Err(SignatureErr::TrailingCharacters);
69 }
70
71 Ok(MethodSignature {
72 type_params,
73 params,
74 ret,
75 throws,
76 })
77 }
78}
79
80fn parse_formal_type_params<I>(it: &mut Peekable<I>) -> Result<Vec<FormalTypeParam>, SignatureErr>
81where
82 I: Iterator<Item = char>,
83{
84 let mut res = Vec::new();
85 loop {
86 let mut name = String::new();
87 loop {
88 let ch = it.next().ok_or(SignatureErr::UnexpectedEnd)?;
89 if ch == ':' {
90 break;
91 }
92 if ch == '>' {
93 return Err(SignatureErr::InvalidIdentifier);
94 }
95 name.push(ch);
96 }
97 if name.is_empty() {
98 return Err(SignatureErr::InvalidIdentifier);
99 }
100
101 let class_bound = match it.peek().copied() {
102 Some(':') => None,
103 Some(_) => Some(JavaType::try_recursive(it)?),
104 None => return Err(SignatureErr::UnexpectedEnd),
105 };
106
107 let mut interface_bounds = Vec::new();
108 while it.peek() == Some(&':') {
109 it.next();
110 if matches!(it.peek(), Some('>')) {
111 return Err(SignatureErr::InvalidBound);
112 }
113 interface_bounds.push(JavaType::try_recursive(it)?);
114 }
115
116 res.push(FormalTypeParam {
117 name,
118 class_bound,
119 interface_bounds,
120 });
121
122 match it.peek().copied() {
123 Some('>') => {
124 it.next();
125 break;
126 }
127 Some(_) => {
128 continue;
129 }
130 None => return Err(SignatureErr::UnexpectedEnd),
131 }
132 }
133 Ok(res)
134}
135
136impl ClassSignature {
137 pub fn new(s: &str, is_interface: bool) -> Result<Self, SignatureErr> {
138 let mut it = s.chars().peekable();
139
140 let type_params = if it.peek() == Some(&'<') {
141 it.next();
142 parse_formal_type_params(&mut it)?
143 } else {
144 Vec::new()
145 };
146
147 let super_class = parse_class_type(&mut it)?.ok_or(SignatureErr::MissingSuper)?;
148
149 let mut interfaces = Vec::new();
150 while it.peek().is_some() {
151 let iface = parse_class_type(&mut it)?.ok_or(SignatureErr::UnexpectedEnd)?;
152 interfaces.push(iface);
153 }
154
155 Ok(ClassSignature {
156 is_interface,
157 type_params,
158 super_class,
159 interfaces,
160 })
161 }
162}
163
164fn parse_class_type<I>(it: &mut Peekable<I>) -> Result<Option<JavaType>, SignatureErr>
165where
166 I: Iterator<Item = char>,
167{
168 if it.peek().is_none() {
169 return Ok(None);
170 }
171 let t = JavaType::try_recursive(it)?;
172 match t {
173 JavaType::Instance(_) | JavaType::GenericInstance(_) => Ok(Some(t)),
174 _ => Err(SignatureErr::InvalidSuperClassType),
175 }
176}
177
178impl fmt::Display for ClassSignature {
179 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
180 if !self.type_params.is_empty() {
181 write!(f, "<")?;
182 for (i, tp) in self.type_params.iter().enumerate() {
183 if i > 0 {
184 write!(f, ", ")?;
185 }
186 write!(f, "{tp}")?;
187 }
188 write!(f, "> ")?;
189 }
190
191 let is_object = self.super_class == JavaType::Instance("java/lang/Object".to_string());
193 if !(self.is_interface && is_object) {
194 write!(f, "extends {}", self.super_class)?;
195 }
196
197 if !self.interfaces.is_empty() {
198 if self.is_interface {
200 write!(f, " extends ")?;
201 } else {
202 write!(f, " implements ")?;
203 }
204 for (i, itf) in self.interfaces.iter().enumerate() {
205 if i > 0 {
206 write!(f, ", ")?;
207 }
208 write!(f, "{itf}")?;
209 }
210 }
211 Ok(())
212 }
213}
214
215impl fmt::Display for MethodSignature {
216 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
217 if !self.type_params.is_empty() {
218 write!(f, "<")?;
219 for (i, tp) in self.type_params.iter().enumerate() {
220 if i > 0 {
221 write!(f, ", ")?;
222 }
223 write!(f, "{tp}")?;
224 }
225 write!(f, "> ")?;
226 }
227
228 write!(f, "{}", self.ret)?;
229
230 Ok(())
231 }
232}
233
234impl MethodSignature {
235 pub fn fmt_throws(&self) -> String {
236 if self.throws.is_empty() {
237 String::new()
238 } else {
239 let throws_str = self
240 .throws
241 .iter()
242 .map(|t| t.to_string())
243 .collect::<Vec<_>>()
244 .join(", ");
245 format!(" throws {throws_str}")
246 }
247 }
248}
249
250impl fmt::Display for FormalTypeParam {
251 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
252 write!(f, "{}", self.name)?;
253 let mut printed_any_bound = false;
254
255 if let Some(cb) = &self.class_bound {
256 write!(f, " extends {}", cb)?;
257 printed_any_bound = true;
258 }
259
260 for ib in &self.interface_bounds {
261 if printed_any_bound {
262 write!(f, " & {}", ib)?;
263 } else {
264 write!(f, " extends {}", ib)?;
265 printed_any_bound = true;
266 }
267 }
268 Ok(())
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::*;
275
276 #[test]
277 fn method_sig_typevar_return_and_bounds() {
278 let sig = MethodSignature::try_from(
279 "<R:Ljava/lang/Object;>(Ljava/util/function/Function<-Ljava/lang/String;+TR;>;)TR;",
280 )
281 .unwrap();
282
283 assert_eq!(sig.type_params.len(), 1);
284 assert_eq!(sig.type_params[0].to_string(), "R extends java.lang.Object");
285
286 assert_eq!(sig.params.len(), 1);
287 assert_eq!(
288 sig.params[0].to_string(),
289 "java.util.function.Function<? super java.lang.String, ? extends R>"
290 );
291
292 assert_eq!(sig.ret.to_string(), "R");
293 }
294}