Skip to main content

lvm_common/
signature.rs

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(); // consume '<'
38            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        // extends Super
192        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            //TODO: probably makes sense to split interfaces and classes structures?
199            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}