1use std::{collections::BTreeMap, sync::Arc};
2
3use inflector::Inflector;
4use proc_macro2::{Delimiter, Ident, Span, TokenStream, TokenTree};
5use quote::quote_spanned;
6
7use crate::{
8 parse::{Parse, TextAccum},
9 upcasts::Upcasts,
10};
11
12#[derive(Debug)]
15pub struct RootMap {
16 pub subpackages: BTreeMap<Id, SpannedPackageInfo>,
17 pub classes: BTreeMap<DotId, Arc<ClassInfo>>,
18 pub upcasts: Upcasts,
19}
20
21impl RootMap {
22 pub fn find_class(&self, cn: &DotId) -> Option<&Arc<ClassInfo>> {
24 self.classes.get(cn)
25 }
26
27 pub fn find_package(&self, ids: &[Id]) -> Option<&SpannedPackageInfo> {
29 let (p0, ps) = ids.split_first().unwrap();
30 self.subpackages.get(p0)?.find_subpackage(ps)
31 }
32
33 pub fn to_packages(&self) -> impl Iterator<Item = &SpannedPackageInfo> {
34 self.subpackages.values()
35 }
36
37 pub fn class_names(&self) -> Vec<DotId> {
39 self.classes.keys().cloned().collect()
40 }
41}
42
43#[derive(Debug)]
44pub struct SpannedPackageInfo {
45 pub name: Id,
46 pub span: Span,
47 pub subpackages: BTreeMap<Id, SpannedPackageInfo>,
48 pub classes: Vec<DotId>,
49}
50
51impl SpannedPackageInfo {
52 pub fn find_subpackage(&self, ids: &[Id]) -> Option<&SpannedPackageInfo> {
54 let Some((p0, ps)) = ids.split_first() else {
55 return Some(self);
56 };
57
58 self.subpackages.get(p0)?.find_subpackage(ps)
59 }
60
61 pub fn find_class(&self, cn: &Id) -> Option<&DotId> {
63 self.classes.iter().find(|c| c.is_class(cn))
64 }
65}
66
67#[derive(Debug)]
68pub enum ClassDecl {
69 Reflected(ReflectedClassInfo),
71
72 Specified(ClassInfo),
74}
75
76impl Parse for ClassDecl {
77 fn parse(p: &mut crate::parse::Parser) -> syn::Result<Option<Self>> {
78 let Some(t0) = p.peek_token() else {
80 return Ok(None);
81 };
82 match t0 {
83 TokenTree::Ident(i) => {
84 static START_KEYWORDS: &[&str] = &[
85 "class",
86 "public",
87 "final",
88 "abstract",
89 "interface",
90 "enum",
91 "record",
92 ];
93 let s = i.to_string();
94 if !START_KEYWORDS.contains(&s.as_str()) {
95 return Ok(None);
96 }
97 }
98 _ => return Ok(None),
99 }
100
101 let t0 = p.eat_token().unwrap();
103 let mut accum = TextAccum::new(p, t0);
104 while let Some(t1) = accum.accum() {
105 match t1 {
106 TokenTree::Group(d) if d.delimiter() == Delimiter::Brace => {
107 break;
108 }
109 _ => {}
110 }
111 }
112
113 let (text, span) = accum.into_accumulated_result();
115 let r = javap::parse_class_decl(span, &text)?;
116 Ok(Some(r))
117 }
118
119 fn description() -> String {
120 format!("class definition (copy/paste the output from `javap -public`)")
121 }
122}
123
124#[derive(Clone, Debug)]
125pub struct ReflectedClassInfo {
126 pub span: Span,
127 #[allow(dead_code)] pub flags: Flags,
129 pub name: DotId,
130 pub kind: ClassKind,
131}
132
133#[derive(Clone, Debug)]
134pub struct ClassInfo {
135 pub span: Span,
136 #[allow(dead_code)] pub flags: Flags,
138 pub name: DotId,
139 pub kind: ClassKind,
140 pub generics: Vec<Generic>,
141 pub extends: Vec<ClassRef>,
142 pub implements: Vec<ClassRef>,
143 pub constructors: Vec<Constructor>,
144 pub fields: Vec<Field>,
145 pub methods: Vec<Method>,
146}
147
148impl ClassInfo {
149 pub fn parse(text: &str, span: Span) -> syn::Result<ClassInfo> {
150 javap::parse_class_info(span, &text)
151 }
152
153 pub fn this_ref(&self) -> ClassRef {
154 ClassRef {
155 name: self.name.clone(),
156 generics: self
157 .generics
158 .iter()
159 .map(|g| RefType::TypeParameter(g.id.clone()))
160 .collect(),
161 }
162 }
163
164 pub fn should_mirror_in_rust(&self, privacy: Privacy) -> bool {
169 match (privacy, self.kind) {
170 (Privacy::Public, _) | (Privacy::Default, ClassKind::Interface) => true,
171
172 (Privacy::Protected, _)
173 | (Privacy::Private, _)
174 | (Privacy::Default, ClassKind::Class) => false,
175 }
176 }
177
178 pub fn generics_scope(&self) -> GenericsScope<'_> {
179 GenericsScope::Generics(&self.generics, &GenericsScope::Empty)
180 }
181}
182
183#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
184pub struct Generic {
185 pub id: Id,
186 pub extends: Vec<ClassRef>,
187}
188
189impl Generic {
190 pub fn to_ident(&self, span: Span) -> Ident {
191 self.id.to_ident(span)
192 }
193}
194
195impl std::fmt::Display for Generic {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(f, "{}", self.id)?;
198 if let Some((e0, e1)) = self.extends.split_first() {
199 write!(f, " extends {e0}")?;
200 for ei in e1 {
201 write!(f, " & {ei}")?;
202 }
203 }
204 Ok(())
205 }
206}
207
208#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Debug)]
209pub enum ClassKind {
210 Class,
211 Interface,
212}
213
214#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Debug)]
215pub struct Flags {
216 pub privacy: Privacy,
217 pub is_final: bool,
218 pub is_synchronized: bool,
219 pub is_native: bool,
220 pub is_abstract: bool,
221 pub is_static: bool,
222 pub is_default: bool,
223 pub is_transient: bool,
224 pub is_volatile: bool,
225}
226
227impl Flags {
228 pub fn new(p: Privacy) -> Self {
229 Flags {
230 privacy: p,
231 is_final: false,
232 is_synchronized: false,
233 is_native: false,
234 is_abstract: false,
235 is_static: false,
236 is_default: false,
237 is_transient: false,
238 is_volatile: false,
239 }
240 }
241}
242
243#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Debug)]
244pub enum Privacy {
245 Public,
246 Protected,
247 Private,
248
249 Default,
253}
254
255impl std::fmt::Display for Privacy {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 match self {
258 Privacy::Public => write!(f, "`public`"),
259 Privacy::Protected => write!(f, "`protected`"),
260 Privacy::Private => write!(f, "`private`"),
261 Privacy::Default => write!(f, "default privacy"),
262 }
263 }
264}
265
266#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
267pub enum MemberFunction {
268 Constructor(Constructor),
269 Method(Method),
270}
271
272#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
273pub struct Constructor {
274 pub flags: Flags,
275 pub generics: Vec<Generic>,
276 pub argument_tys: Vec<Type>,
277 pub throws: Vec<ClassRef>,
278}
279
280impl Constructor {
281 pub fn to_method_sig(&self, class: &ClassInfo) -> MethodSig {
282 MethodSig {
283 name: class.name.class_name().clone(),
284 generics: self.generics.clone(),
285 argument_tys: self.argument_tys.clone(),
286 }
287 }
288
289 pub fn descriptor(&self, ctx: &GenericsScope<'_>) -> String {
295 let ctx = &ctx.nest(&self.generics);
296 format!(
297 "({})V",
298 self.argument_tys
299 .iter()
300 .map(|a| a.descriptor(ctx))
301 .collect::<String>()
302 )
303 }
304}
305
306#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
307pub struct Field {
308 pub flags: Flags,
309 pub name: Id,
310 pub ty: Type,
311}
312
313#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
314pub struct Method {
315 pub flags: Flags,
316 pub name: Id,
317 pub generics: Vec<Generic>,
318 pub argument_tys: Vec<Type>,
319 pub return_ty: Option<Type>,
320 pub throws: Vec<ClassRef>,
321}
322
323impl Method {
324 pub fn to_method_sig(&self) -> MethodSig {
325 MethodSig {
326 name: self.name.clone(),
327 generics: self.generics.clone(),
328 argument_tys: self.argument_tys.clone(),
329 }
330 }
331
332 pub fn descriptor(&self, ctx: &GenericsScope<'_>) -> String {
338 let ctx = &ctx.nest(&self.generics);
339 format!(
340 "({}){}",
341 self.argument_tys
342 .iter()
343 .map(|a| a.descriptor(ctx))
344 .collect::<String>(),
345 self.return_ty
346 .as_ref()
347 .map(|r| r.descriptor(ctx))
348 .unwrap_or_else(|| format!("V")),
349 )
350 }
351}
352
353#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
357pub struct MethodSig {
358 pub name: Id,
359 pub generics: Vec<Generic>,
360 pub argument_tys: Vec<Type>,
361}
362
363impl std::fmt::Display for MethodSig {
364 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
365 if let Some((generic_id0, generic_ids)) = self.generics.split_first() {
366 write!(f, "<{generic_id0}")?;
367 for id in generic_ids {
368 write!(f, ", {id}")?;
369 }
370 write!(f, "> ")?;
371 }
372 write!(f, "{}(", self.name)?;
373 if let Some((ty0, tys)) = self.argument_tys.split_first() {
374 write!(f, "{ty0}")?;
375 for ty in tys {
376 write!(f, ", {ty}")?;
377 }
378 }
379 write!(f, ")")?;
380 Ok(())
381 }
382}
383
384#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
385pub struct ClassRef {
386 pub name: DotId,
387 pub generics: Vec<RefType>,
388}
389
390impl std::fmt::Display for ClassRef {
391 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
392 write!(f, "{}", self.name)?;
393 if let Some((ty0, tys)) = self.generics.split_first() {
394 write!(f, "<{ty0}")?;
395 for ty in tys {
396 write!(f, ", {ty}")?;
397 }
398 write!(f, ">")?;
399 }
400 Ok(())
401 }
402}
403
404#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
405pub enum Type {
406 Ref(RefType),
407 Scalar(ScalarType),
408 Repeat(Arc<Type>),
409}
410
411impl From<ClassRef> for Type {
412 fn from(value: ClassRef) -> Self {
413 Type::Ref(RefType::Class(value))
414 }
415}
416
417impl std::fmt::Display for Type {
418 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
419 match self {
420 Type::Ref(t) => write!(f, "{t}"),
421 Type::Scalar(t) => write!(f, "{t}"),
422 Type::Repeat(t) => write!(f, "{t}..."),
423 }
424 }
425}
426
427impl Type {
428 pub fn is_scalar(&self) -> bool {
429 match self {
430 Type::Scalar(_) => true,
431 Type::Ref(_) | Type::Repeat(_) => false,
432 }
433 }
434
435 pub fn to_non_repeating(&self) -> NonRepeatingType {
438 match self {
439 Type::Ref(t) => NonRepeatingType::Ref(t.clone()),
440 Type::Scalar(t) => NonRepeatingType::Scalar(t.clone()),
441 Type::Repeat(t) => NonRepeatingType::Ref(RefType::Array(t.clone())),
442 }
443 }
444
445 pub fn descriptor(&self, ctx: &GenericsScope<'_>) -> String {
451 self.to_non_repeating().descriptor(ctx)
452 }
453}
454
455pub enum GenericsScope<'a> {
459 Empty,
460 Generics(&'a [Generic], &'a GenericsScope<'a>),
461}
462
463impl<'a> GenericsScope<'a> {
464 fn find(&self, ty: &Id) -> Option<&Generic> {
466 match self {
467 GenericsScope::Empty => None,
468 GenericsScope::Generics(g, inner) => g.iter().find(|g| &g.id == ty).or(inner.find(ty)),
469 }
470 }
471
472 fn nest(&'a self, generics: &'a [Generic]) -> GenericsScope<'a> {
477 GenericsScope::Generics(generics, self)
478 }
479}
480
481#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
483pub enum NonRepeatingType {
484 Ref(RefType),
485 Scalar(ScalarType),
486}
487
488impl NonRepeatingType {
489 pub fn descriptor(&self, ctx: &GenericsScope<'_>) -> String {
495 match self {
496 NonRepeatingType::Ref(r) => match r {
497 RefType::Class(c) => format!("L{};", c.name.to_jni_name()),
498 RefType::Array(r) => format!("[{}", r.descriptor(ctx)),
499
500 RefType::TypeParameter(id) => {
501 let generic = ctx.find(id).expect("generic did not exist.");
502 match generic.extends.get(0) {
503 Some(c) => format!("L{};", c.name.to_jni_name()),
504 _ => format!("Ljava/lang/Object;"),
505 }
506 }
507 RefType::Extends(_) | RefType::Super(_) | RefType::Wildcard => {
508 format!("Ljava/lang/Object;")
509 }
510 },
511 NonRepeatingType::Scalar(s) => match s {
512 ScalarType::Int => format!("I"),
513 ScalarType::Long => format!("J"),
514 ScalarType::Short => format!("S"),
515 ScalarType::Byte => format!("B"),
516 ScalarType::F64 => format!("D"),
517 ScalarType::F32 => format!("F"),
518 ScalarType::Boolean => format!("Z"),
519 ScalarType::Char => format!("C"),
520 },
521 }
522 }
523}
524
525#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
526pub enum RefType {
527 Class(ClassRef),
528 Array(Arc<Type>),
529 TypeParameter(Id),
530 Extends(Arc<RefType>),
531 Super(Arc<RefType>),
532 Wildcard,
533}
534
535impl std::fmt::Display for RefType {
536 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
537 match self {
538 RefType::Class(c) => write!(f, "{c}"),
539 RefType::Array(e) => write!(f, "{e}[]"),
540 RefType::TypeParameter(id) => write!(f, "{id}"),
541 RefType::Extends(t) => write!(f, "? extends {t}"),
542 RefType::Super(t) => write!(f, "? super {t}"),
543 RefType::Wildcard => write!(f, "?"),
544 }
545 }
546}
547
548#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug)]
549pub enum ScalarType {
550 Int,
551 Long,
552 Short,
553 Byte,
554 F64,
555 F32,
556 Boolean,
557 Char,
558}
559
560impl std::fmt::Display for ScalarType {
561 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
562 match self {
563 ScalarType::Int => write!(f, "int"),
564 ScalarType::Long => write!(f, "long"),
565 ScalarType::Short => write!(f, "long"),
566 ScalarType::Byte => write!(f, "byte"),
567 ScalarType::F64 => write!(f, "double"),
568 ScalarType::F32 => write!(f, "float"),
569 ScalarType::Boolean => write!(f, "boolean"),
570 ScalarType::Char => write!(f, "char"),
571 }
572 }
573}
574
575impl ScalarType {
576 pub fn to_tokens(&self, span: Span) -> TokenStream {
577 match self {
578 ScalarType::Char => quote_spanned!(span => u16),
579 ScalarType::Int => quote_spanned!(span => i32),
580 ScalarType::Long => quote_spanned!(span => i64),
581 ScalarType::Short => quote_spanned!(span => i16),
582 ScalarType::Byte => quote_spanned!(span => i8),
583 ScalarType::F64 => quote_spanned!(span => f64),
584 ScalarType::F32 => quote_spanned!(span => f32),
585 ScalarType::Boolean => quote_spanned!(span => bool),
586 }
587 }
588}
589
590#[derive(Eq, Hash, Ord, PartialEq, PartialOrd, Clone, Debug)]
592pub struct Id {
593 pub data: String,
594}
595
596impl std::ops::Deref for Id {
597 type Target = String;
598
599 fn deref(&self) -> &String {
600 &self.data
601 }
602}
603
604impl From<String> for Id {
605 fn from(value: String) -> Self {
606 Id { data: value }
607 }
608}
609
610impl From<&str> for Id {
611 fn from(value: &str) -> Self {
612 Id {
613 data: value.to_owned(),
614 }
615 }
616}
617
618impl Id {
619 pub fn dot(self, s: &str) -> DotId {
620 DotId::from(self).dot(s)
621 }
622
623 pub fn to_ident(&self, span: Span) -> Ident {
624 let data = self.data.replace("$", "__");
625 let mut ident = syn::parse_str(data.as_str()).unwrap_or_else(|_| Ident::new_raw(&data, span));
628 ident.set_span(span);
629 ident
630 }
631
632 pub fn to_snake_case(&self) -> Self {
633 Self {
634 data: self.data.to_snake_case(),
635 }
636 }
637}
638
639impl std::fmt::Display for Id {
640 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
641 write!(f, "{}", self.data)
642 }
643}
644
645#[derive(Eq, Hash, Ord, PartialEq, PartialOrd, Clone, Debug)]
647pub struct DotId {
648 ids: Vec<Id>,
650}
651
652impl From<Id> for DotId {
653 fn from(value: Id) -> Self {
654 DotId { ids: vec![value] }
655 }
656}
657
658impl From<&Id> for DotId {
659 fn from(value: &Id) -> Self {
660 DotId {
661 ids: vec![value.clone()],
662 }
663 }
664}
665
666impl FromIterator<Id> for DotId {
667 fn from_iter<T: IntoIterator<Item = Id>>(iter: T) -> Self {
668 let ids: Vec<Id> = iter.into_iter().collect();
669 assert!(ids.len() >= 1);
670 DotId { ids }
671 }
672}
673
674impl DotId {
675 pub fn new(package: &[Id], class: &Id) -> Self {
676 DotId {
677 ids: package
678 .iter()
679 .chain(std::iter::once(class))
680 .cloned()
681 .collect(),
682 }
683 }
684
685 pub fn object() -> Self {
686 Self::parse("java.lang.Object")
687 }
688
689 pub fn exception() -> Self {
690 Self::parse("java.lang.Exception")
691 }
692
693 pub fn runtime_exception() -> Self {
694 Self::parse("java.lang.RuntimeException")
695 }
696
697 pub fn throwable() -> Self {
698 Self::parse("java.lang.Throwable")
699 }
700
701 pub fn parse(s: impl AsRef<str>) -> DotId {
702 let s: &str = s.as_ref();
703 let ids: Vec<Id> = s.split(".").map(Id::from).collect();
704 assert!(ids.len() > 1, "bad input to DotId::parse: {s:?}");
705 DotId { ids }
706 }
707
708 pub fn dot(mut self, s: &str) -> DotId {
709 self.ids.push(Id::from(s));
710 self
711 }
712
713 pub fn is_class(&self, s: &Id) -> bool {
714 self.split().1 == s
715 }
716
717 pub fn to_jni_class_name(&self) -> Id {
720 self.split().1.data.replace("_", "_1").into()
721 }
722
723 pub fn class_name(&self) -> &Id {
724 self.split().1
725 }
726
727 pub fn to_jni_package(&self) -> String {
730 self.split()
731 .0
732 .iter()
733 .map(|id| id.data.replace("_", "_1"))
734 .collect::<Vec<_>>()
735 .join("_")
736 }
737
738 pub fn split(&self) -> (&[Id], &Id) {
740 let (name, package) = self.ids.split_last().unwrap();
741 (package, name)
742 }
743
744 pub fn to_jni_name(&self) -> String {
746 self.ids
747 .iter()
748 .map(|id| &id[..])
749 .collect::<Vec<_>>()
750 .join("/")
751 }
752
753 pub fn to_module_name(&self, span: Span) -> TokenStream {
755 let (package_names, struct_name) = self.split();
756 let struct_ident = struct_name.to_ident(span);
757 let package_idents: Vec<Ident> = package_names.iter().map(|n| n.to_ident(span)).collect();
758 quote_spanned!(span => #(#package_idents ::)* #struct_ident)
759 }
760}
761
762impl std::ops::Deref for DotId {
763 type Target = [Id];
764
765 fn deref(&self) -> &Self::Target {
766 &self.ids
767 }
768}
769
770impl std::fmt::Display for DotId {
771 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
772 let (package, class) = self.split();
773 for id in package {
774 write!(f, "{id}.")?;
775 }
776 write!(f, "{class}")?;
777 Ok(())
778 }
779}
780
781mod javap;