classfile,passes: model runtime-visible annotations, rewrite their descriptors
This commit is contained in:
parent
4b14eeb40f
commit
48a5bc23a9
13 changed files with 527 additions and 4 deletions
|
|
@ -144,3 +144,124 @@ fn permitted_subclasses_round_trip() {
|
|||
let ir = round_trip(&rt);
|
||||
assert_eq!(ir.this_class, "demo/Sealed");
|
||||
}
|
||||
|
||||
/// Runtime-visible annotations on a method survive the round trip: the
|
||||
/// pool is rebuilt on write, so raw index blobs would go stale and
|
||||
/// reflection (`Method.getAnnotation`) would die with
|
||||
/// `AnnotationFormatError`/`GenericSignatureFormatError`.
|
||||
#[test]
|
||||
fn runtime_visible_annotations_round_trip() {
|
||||
use ristretto_classfile::attributes::{
|
||||
Annotation as RtAnno, AnnotationElement as RtElem, AnnotationValuePair as RtPair,
|
||||
};
|
||||
let mut pool = ConstantPool::default();
|
||||
let this = pool.add_class("demo/Anno").expect("this");
|
||||
let object = pool.add_class("java/lang/Object").expect("object");
|
||||
let name = pool.add_utf8("run").expect("name");
|
||||
let desc = pool.add_utf8("()V").expect("desc");
|
||||
let code_name = pool.add_utf8("Code").expect("code");
|
||||
let attr_name = pool.add_utf8("RuntimeVisibleAnnotations").expect("rva");
|
||||
let marker = pool.add_utf8("Ldemo/Marker;").expect("marker");
|
||||
let value_key = pool.add_utf8("value").expect("value key");
|
||||
let hello = pool.add_utf8("hello").expect("hello");
|
||||
let klass_key = pool.add_utf8("klass").expect("klass key");
|
||||
let target = pool.add_utf8("Ldemo/Target;").expect("target");
|
||||
let kind_key = pool.add_utf8("kind").expect("kind key");
|
||||
let kind_type = pool.add_utf8("Ldemo/Kind;").expect("kind type");
|
||||
let one = pool.add_utf8("ONE").expect("one");
|
||||
let nested_key = pool.add_utf8("nested").expect("nested key");
|
||||
let nested_type = pool.add_utf8("Ldemo/Nested;").expect("nested type");
|
||||
let arr_key = pool.add_utf8("arr").expect("arr key");
|
||||
let seven = pool.add_integer(7).expect("seven");
|
||||
|
||||
let annotation = RtAnno {
|
||||
type_index: marker,
|
||||
elements: vec![
|
||||
RtPair {
|
||||
name_index: value_key,
|
||||
value: RtElem::String {
|
||||
const_value_index: hello,
|
||||
},
|
||||
},
|
||||
RtPair {
|
||||
name_index: klass_key,
|
||||
value: RtElem::Class {
|
||||
class_info_index: target,
|
||||
},
|
||||
},
|
||||
RtPair {
|
||||
name_index: kind_key,
|
||||
value: RtElem::Enum {
|
||||
type_name_index: kind_type,
|
||||
const_name_index: one,
|
||||
},
|
||||
},
|
||||
RtPair {
|
||||
name_index: nested_key,
|
||||
value: RtElem::Annotation {
|
||||
annotation: RtAnno {
|
||||
type_index: nested_type,
|
||||
elements: vec![],
|
||||
},
|
||||
},
|
||||
},
|
||||
RtPair {
|
||||
name_index: arr_key,
|
||||
value: RtElem::Array {
|
||||
values: vec![
|
||||
RtElem::String {
|
||||
const_value_index: hello,
|
||||
},
|
||||
RtElem::Int {
|
||||
const_value_index: seven,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let rt = RtClass {
|
||||
version: JAVA_21,
|
||||
constant_pool: pool,
|
||||
access_flags: ClassAccessFlags::PUBLIC,
|
||||
this_class: this,
|
||||
super_class: object,
|
||||
interfaces: vec![],
|
||||
fields: vec![],
|
||||
methods: vec![RtMethod {
|
||||
access_flags: MethodAccessFlags::PUBLIC | MethodAccessFlags::STATIC,
|
||||
name_index: name,
|
||||
descriptor_index: desc,
|
||||
attributes: vec![
|
||||
RtAttr::Code {
|
||||
name_index: code_name,
|
||||
max_stack: 0,
|
||||
max_locals: 1,
|
||||
code: vec![Rt::Return],
|
||||
exception_table: vec![],
|
||||
attributes: vec![],
|
||||
},
|
||||
RtAttr::RuntimeVisibleAnnotations {
|
||||
name_index: attr_name,
|
||||
annotations: vec![annotation],
|
||||
},
|
||||
],
|
||||
}],
|
||||
attributes: vec![],
|
||||
..RtClass::default()
|
||||
};
|
||||
|
||||
let ir = round_trip(&rt);
|
||||
let attrs = &ir.methods[0].attributes;
|
||||
let annos = attrs
|
||||
.iter()
|
||||
.find_map(|a| match a {
|
||||
noxis_classfile::Attribute::RuntimeVisibleAnnotations(list) => Some(list),
|
||||
_ => None,
|
||||
})
|
||||
.expect("annotations modeled");
|
||||
assert_eq!(annos.len(), 1);
|
||||
assert_eq!(annos[0].descriptor, "Ldemo/Marker;");
|
||||
assert_eq!(annos[0].elements.len(), 5);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue