classfile,passes: model runtime-visible annotations, rewrite their descriptors

This commit is contained in:
Loki 2026-10-11 13:02:26 +02:00
parent 4b14eeb40f
commit 48a5bc23a9
Signed by: boba
GPG key ID: 253067914055423B
13 changed files with 527 additions and 4 deletions

View file

@ -0,0 +1,42 @@
//! Runtime-visible/invisible annotations: names instead of pool indices.
//!
//! Raw `info` blobs go stale the moment the pool is rebuilt on write, and
//! the JVM's reflection parser then dies with `AnnotationFormatError` or
//! reads neighboring attribute bytes as signatures.
/// One `annotation` structure: the type descriptor + element-value pairs.
#[derive(Debug, Clone, PartialEq)]
pub struct Annotation {
/// The annotation type as a field descriptor (`Lpkg/Ann;`).
pub descriptor: String,
/// `(element name, value)` pairs in class-file order.
pub elements: Vec<(String, AnnotationValue)>,
}
/// A single `element_value`: one variant per tag, so `B`/`C`/`S`/`Z`
/// keep their identity (the pool stores them all as `CONSTANT_Integer`,
/// but HotSpot checks the tag against the annotation member's type).
#[derive(Debug, Clone, PartialEq)]
pub enum AnnotationValue {
Byte(i32),
Char(i32),
Double(f64),
Float(f32),
Int(i32),
Long(i64),
Short(i32),
Boolean(i32),
/// The `s` tag: a `CONSTANT_Utf8`, not a `CONSTANT_String`.
String(String),
/// The `e` tag: enum type descriptor + constant name.
Enum {
descriptor: String,
name: String,
},
/// The `c` tag: a class-info descriptor (`Ljava/lang/String;` or `I`).
Class(String),
/// The `@` tag: a nested annotation.
Nested(Box<Annotation>),
/// The `[` tag: array of values.
Array(Vec<AnnotationValue>),
}

View file

@ -1,8 +1,10 @@
//! The "program" structure - the unit of work for the pipeline.
pub mod annotations;
pub mod builder;
pub mod version;
pub use annotations::{Annotation, AnnotationValue};
pub use version::Version;
use crate::format::StackMapFrame;
@ -41,6 +43,11 @@ pub enum Attribute {
Record(Vec<RecordComponent>),
/// `LocalVariableTypeTable`: generic local signatures (like LVT).
LocalVariableTypeTable(Vec<LocalVariableType>),
/// `RuntimeVisibleAnnotations` (JVMS §4.7.16): parsed, not raw bytes -
/// reflection reads them at runtime and raw indices go stale on write.
RuntimeVisibleAnnotations(Vec<Annotation>),
/// `RuntimeInvisibleAnnotations` (JVMS §4.7.17): CLASS-retention ones.
RuntimeInvisibleAnnotations(Vec<Annotation>),
/// Everything else: name + raw `info` bytes (careful with pool indices).
Raw {
name: String,