Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d9dfce0
Add trimmable [Export] callback support
simonrozsival Apr 13, 2026
22d6b11
Refactor [Export] code generation
simonrozsival Apr 13, 2026
6b69c63
Exclude Mono.Android.Export from trimmable packages
simonrozsival Apr 13, 2026
9e92791
Refine export method dispatch model
simonrozsival Apr 13, 2026
2c8dae7
Scope export method dispatch emission
simonrozsival Apr 13, 2026
ce1aa36
Tighten trimmable export cleanup
simonrozsival Apr 13, 2026
f6232bb
Propagate deferred registerNatives to base classes and fix test plumbing
simonrozsival Apr 13, 2026
67ecfbd
Remove unrelated changes: revert test plumbing, CI lane, and manifest…
simonrozsival Apr 16, 2026
a0e5e30
Revert whitespace-only changes and restore EmitRegisterNatives position
simonrozsival Apr 16, 2026
f2aa14e
Fix stack corruption in TryEmitExportParameterArgument
simonrozsival Apr 16, 2026
c6fe56d
Revert MonoAndroidExportTest changes that force trimmable typemap
simonrozsival Apr 17, 2026
d0acd52
Fix instrumentation targetPackage default
simonrozsival Apr 18, 2026
88ca58f
Fix missing 'static' keyword in Java codegen for static [Export] methods
simonrozsival Apr 21, 2026
430d5e3
Address review: perf optimization + code organization
simonrozsival Apr 21, 2026
c4aac55
Fix test: TypeMapAssociationAttribute is no longer generic
simonrozsival Apr 22, 2026
d8dc37f
Remove dead ManagedParameterTypeNames/ManagedReturnTypeName propertie…
simonrozsival Apr 22, 2026
80b2986
Fix test: TypeMapAssociationAttribute is generic (TypeMapAssociationA…
simonrozsival Apr 26, 2026
e6b38e1
Restore ExcludedTestNames for trimmable typemap tests
simonrozsival Apr 26, 2026
ffb5093
Trimmable typemap: invoke user-visible parameterless ctor in UCO wrap…
simonrozsival Apr 26, 2026
308a961
Fix bad-rebase artifacts: restore CI lane and submodule SHA
simonrozsival Apr 27, 2026
85e0b65
Reduce diff churn against base
simonrozsival Apr 27, 2026
f136461
Drop unnecessary Java_mono_android_Runtime_registerNatives JNI export
simonrozsival Apr 27, 2026
d49ba61
Move EmitRegisterNatives + AddUnmanagedCallersOnlyAttribute back to o…
simonrozsival Apr 27, 2026
586eeda
Clean up UCO ctor comment: drop test-specific detail, point at the sa…
simonrozsival Apr 27, 2026
e5c7810
Address review feedback: lazy export emitter, hoist deferred check, d…
simonrozsival Apr 27, 2026
deb6874
Add device tests for parameterized ctor activation contract
simonrozsival Apr 27, 2026
4aaf705
Redesign parameterized ctor activation tests around Throwable args
simonrozsival Apr 27, 2026
c1cc2b6
[trimmable typemap] Gate user-ctor UCO emission on matching managed .…
simonrozsival Apr 27, 2026
5d623bf
[trimmable typemap] Forward JNI args to user-visible parameterized .ctor
simonrozsival Apr 27, 2026
f438f1f
[trimmable typemap] Simplify ManagedParameterTypes plumbing
simonrozsival Apr 27, 2026
1f6ffbf
[trimmable typemap] Extract user-visible ctor wrapper emission helper
simonrozsival Apr 27, 2026
07b14f9
Reuse export primitive marshalling for parameterized UCO ctor args
simonrozsival Apr 27, 2026
71317c0
Add Mono.Android.NET-Tests device coverage for [Export] marshalling
simonrozsival Apr 27, 2026
bca9cd1
Wrap [Export] UCO methods with OnUserUnhandledException routing
simonrozsival Apr 27, 2026
27dfe39
Skip parameterized [Export] ctors with unsupported types
simonrozsival Apr 27, 2026
c6c8ea6
Update [Export] throws tests for OnUserUnhandledException semantics
simonrozsival Apr 27, 2026
8835615
Marshal enum [Export] params/returns via underlying primitive JNI ABI
simonrozsival Apr 27, 2026
82dc863
Marshal ICharSequence and non-generic collection [Export] returns via…
simonrozsival Apr 27, 2026
e5767fa
Update export-comparison.md to reflect Phase 1 marshalling parity work
simonrozsival Apr 27, 2026
e06d2d2
Make enum scanner resolution assembly-aware and resilient to FQN coll…
simonrozsival Apr 27, 2026
372c1ac
Simplify enum scanner helpers in JavaPeerScanner
simonrozsival Apr 27, 2026
9292fc6
Remove export-comparison.md — analysis doc not intended for merge
simonrozsival Apr 27, 2026
ef712f0
Add scanner integration coverage for advanced [Export] shapes
simonrozsival Apr 27, 2026
f1272b9
Scanner integration: cover [ExportField] and [ExportParameter]; fix u…
simonrozsival Apr 27, 2026
f577304
Phase A scanner coverage: dispatch & declaration shapes
simonrozsival Apr 27, 2026
fb8ed6c
Phase B scanner coverage: edge marshalling shapes
simonrozsival Apr 27, 2026
e2a45df
Phase C scanner coverage: robustness shapes
simonrozsival Apr 27, 2026
16382c2
Fix trimmable export rebase fallout
simonrozsival May 5, 2026
a730499
Merge branch 'main' into dev/simonrozsival/trimmable-typemap-export-a…
Copilot May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

namespace Microsoft.Android.Sdk.TrimmableTypeMap;

/// <summary>
/// Holds pre-resolved metadata references needed by <see cref="ExportMethodDispatchEmitter"/>
/// for generating [Export] method dispatch IL. Created once per emit pass and reused
/// for all export methods.
/// </summary>
sealed class ExportMethodDispatchEmitterContext
{
public static ExportMethodDispatchEmitterContext Create (
PEAssemblyBuilder pe,
TypeReferenceHandle iJavaPeerableRef,
TypeReferenceHandle jniHandleOwnershipRef,
TypeReferenceHandle jniEnvRef,
TypeReferenceHandle systemTypeRef,
MemberReferenceHandle getTypeFromHandleRef,
MemberReferenceHandle ucoAttrCtorRef,
BlobHandle ucoAttrBlobHandle,
TypeReferenceHandle jniTransitionRef,
TypeReferenceHandle jniRuntimeRef,
TypeReferenceHandle exceptionRef,
MemberReferenceHandle beginMarshalMethodRef,
MemberReferenceHandle endMarshalMethodRef,
MemberReferenceHandle onUserUnhandledExceptionRef)
{
var metadata = pe.Metadata;
var iJavaObjectRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("IJavaObject"));
var javaLangObjectRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Java.Lang"), metadata.GetOrAddString ("Object"));
var systemArrayRef = metadata.AddTypeReference (pe.SystemRuntimeRef,
metadata.GetOrAddString ("System"), metadata.GetOrAddString ("Array"));
var systemStreamRef = metadata.AddTypeReference (pe.SystemRuntimeRef,
metadata.GetOrAddString ("System.IO"), metadata.GetOrAddString ("Stream"));
var systemXmlRef = pe.FindOrAddAssemblyRef ("System.Xml.ReaderWriter");
var systemXmlReaderRef = metadata.AddTypeReference (systemXmlRef,
metadata.GetOrAddString ("System.Xml"), metadata.GetOrAddString ("XmlReader"));
var inputStreamInvokerRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("InputStreamInvoker"));
var outputStreamInvokerRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("OutputStreamInvoker"));
var inputStreamAdapterRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("InputStreamAdapter"));
var outputStreamAdapterRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("OutputStreamAdapter"));
var xmlPullParserReaderRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("XmlPullParserReader"));
var xmlResourceParserReaderRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("XmlResourceParserReader"));
var xmlReaderPullParserRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("XmlReaderPullParser"));
var xmlReaderResourceParserRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("XmlReaderResourceParser"));
var charSequenceRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("CharSequence"));
var iCharSequenceRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Java.Lang"), metadata.GetOrAddString ("ICharSequence"));
var javaListRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("JavaList"));
var javaDictionaryRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("JavaDictionary"));
var javaCollectionRef = metadata.AddTypeReference (pe.MonoAndroidRef,
metadata.GetOrAddString ("Android.Runtime"), metadata.GetOrAddString ("JavaCollection"));
var systemCollectionsIListRef = metadata.AddTypeReference (pe.SystemRuntimeRef,
metadata.GetOrAddString ("System.Collections"), metadata.GetOrAddString ("IList"));
var systemCollectionsIDictionaryRef = metadata.AddTypeReference (pe.SystemRuntimeRef,
metadata.GetOrAddString ("System.Collections"), metadata.GetOrAddString ("IDictionary"));
var systemCollectionsICollectionRef = metadata.AddTypeReference (pe.SystemRuntimeRef,
metadata.GetOrAddString ("System.Collections"), metadata.GetOrAddString ("ICollection"));

return new ExportMethodDispatchEmitterContext {
IJavaObjectRef = iJavaObjectRef,
GetTypeFromHandleRef = getTypeFromHandleRef,
JniEnvGetStringRef = pe.AddMemberRef (jniEnvRef, "GetString",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().String (),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
})),
JniEnvGetArrayRef = pe.AddMemberRef (jniEnvRef, "GetArray",
sig => sig.MethodSignature ().Parameters (3,
rt => rt.Type ().Type (systemArrayRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
p.AddParameter ().Type ().Type (systemTypeRef, false);
})),
JniEnvCopyArrayRef = pe.AddMemberRef (jniEnvRef, "CopyArray",
sig => sig.MethodSignature ().Parameters (3,
rt => rt.Void (),
p => {
p.AddParameter ().Type ().Type (systemArrayRef, false);
p.AddParameter ().Type ().Type (systemTypeRef, false);
p.AddParameter ().Type ().IntPtr ();
})),
JniEnvNewArrayRef = pe.AddMemberRef (jniEnvRef, "NewArray",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().IntPtr (),
p => {
p.AddParameter ().Type ().Type (systemArrayRef, false);
p.AddParameter ().Type ().Type (systemTypeRef, false);
})),
JniEnvNewStringRef = pe.AddMemberRef (jniEnvRef, "NewString",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().String ())),
JniEnvToLocalJniHandleRef = pe.AddMemberRef (jniEnvRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (iJavaObjectRef, false))),
JavaLangObjectGetObjectRef = pe.AddMemberRef (javaLangObjectRef, "GetObject",
sig => sig.MethodSignature ().Parameters (3,
rt => rt.Type ().Type (iJavaPeerableRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
p.AddParameter ().Type ().Type (systemTypeRef, false);
})),
InputStreamInvokerFromJniHandleRef = pe.AddMemberRef (inputStreamInvokerRef, "FromJniHandle",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().Type (systemStreamRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
})),
OutputStreamInvokerFromJniHandleRef = pe.AddMemberRef (outputStreamInvokerRef, "FromJniHandle",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().Type (systemStreamRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
})),
InputStreamAdapterToLocalJniHandleRef = pe.AddMemberRef (inputStreamAdapterRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemStreamRef, false))),
OutputStreamAdapterToLocalJniHandleRef = pe.AddMemberRef (outputStreamAdapterRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemStreamRef, false))),
XmlPullParserReaderFromJniHandleRef = pe.AddMemberRef (xmlPullParserReaderRef, "FromJniHandle",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().Type (systemXmlReaderRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
})),
XmlResourceParserReaderFromJniHandleRef = pe.AddMemberRef (xmlResourceParserReaderRef, "FromJniHandle",
sig => sig.MethodSignature ().Parameters (2,
rt => rt.Type ().Type (systemXmlReaderRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (jniHandleOwnershipRef, true);
})),
XmlReaderPullParserToLocalJniHandleRef = pe.AddMemberRef (xmlReaderPullParserRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemXmlReaderRef, false))),
XmlReaderResourceParserToLocalJniHandleRef = pe.AddMemberRef (xmlReaderResourceParserRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemXmlReaderRef, false))),
CharSequenceToLocalJniHandleRef = pe.AddMemberRef (charSequenceRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (iCharSequenceRef, false))),
JavaListToLocalJniHandleRef = pe.AddMemberRef (javaListRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemCollectionsIListRef, false))),
JavaDictionaryToLocalJniHandleRef = pe.AddMemberRef (javaDictionaryRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemCollectionsIDictionaryRef, false))),
JavaCollectionToLocalJniHandleRef = pe.AddMemberRef (javaCollectionRef, "ToLocalJniHandle",
sig => sig.MethodSignature ().Parameters (1,
rt => rt.Type ().IntPtr (),
p => p.AddParameter ().Type ().Type (systemCollectionsICollectionRef, false))),
UcoAttrCtorRef = ucoAttrCtorRef,
UcoAttrBlobHandle = ucoAttrBlobHandle,
JniTransitionRef = jniTransitionRef,
JniRuntimeRef = jniRuntimeRef,
ExceptionRef = exceptionRef,
BeginMarshalMethodRef = beginMarshalMethodRef,
EndMarshalMethodRef = endMarshalMethodRef,
OnUserUnhandledExceptionRef = onUserUnhandledExceptionRef,
};
}

public required TypeReferenceHandle IJavaObjectRef { get; init; }
public required MemberReferenceHandle GetTypeFromHandleRef { get; init; }
public required MemberReferenceHandle JniEnvGetStringRef { get; init; }
public required MemberReferenceHandle JniEnvGetArrayRef { get; init; }
public required MemberReferenceHandle JniEnvCopyArrayRef { get; init; }
public required MemberReferenceHandle JniEnvNewArrayRef { get; init; }
public required MemberReferenceHandle JniEnvNewStringRef { get; init; }
public required MemberReferenceHandle JniEnvToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle JavaLangObjectGetObjectRef { get; init; }
public required MemberReferenceHandle InputStreamInvokerFromJniHandleRef { get; init; }
public required MemberReferenceHandle OutputStreamInvokerFromJniHandleRef { get; init; }
public required MemberReferenceHandle InputStreamAdapterToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle OutputStreamAdapterToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle XmlPullParserReaderFromJniHandleRef { get; init; }
public required MemberReferenceHandle XmlResourceParserReaderFromJniHandleRef { get; init; }
public required MemberReferenceHandle XmlReaderPullParserToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle XmlReaderResourceParserToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle CharSequenceToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle JavaListToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle JavaDictionaryToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle JavaCollectionToLocalJniHandleRef { get; init; }
public required MemberReferenceHandle UcoAttrCtorRef { get; init; }

public required BlobHandle UcoAttrBlobHandle { get; init; }

// Marshal-method wrapper plumbing — mirrors the UCO ctor wrapper used by
// TypeMapAssemblyEmitter so that managed exceptions thrown from [Export] method
// bodies surface as Java exceptions instead of crashing the runtime.
public required TypeReferenceHandle JniTransitionRef { get; init; }
public required TypeReferenceHandle JniRuntimeRef { get; init; }
public required TypeReferenceHandle ExceptionRef { get; init; }
public required MemberReferenceHandle BeginMarshalMethodRef { get; init; }
public required MemberReferenceHandle EndMarshalMethodRef { get; init; }
public required MemberReferenceHandle OnUserUnhandledExceptionRef { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,14 @@ static void WriteMethods (JavaPeerInfo type, TextWriter writer)
""");
} else {
string access = method.IsExport && method.JavaAccess != null ? method.JavaAccess : "public";
string staticKeyword = method.IsStatic ? "static " : "";
writer.Write ($$"""

{{access}} {{javaReturnType}} {{method.JniName}} ({{parameters}}){{throwsClause}}
{{access}} {{staticKeyword}}{{javaReturnType}} {{method.JniName}} ({{parameters}}){{throwsClause}}
{
{{registerNativesLine}} {{returnPrefix}}{{method.NativeCallbackName}} ({{args}});
}
{{access}} native {{javaReturnType}} {{method.NativeCallbackName}} ({{parameters}});
{{access}} {{staticKeyword}}native {{javaReturnType}} {{method.NativeCallbackName}} ({{parameters}});

""");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ sealed class JavaPeerProxyData
/// </summary>
public bool IsGenericDefinition { get; init; }

/// <summary>
/// True when the Java stub must not call RegisterNatives from a static initializer because
/// the type can be instantiated before the runtime is fully ready (for example Application
/// or Instrumentation subclasses).
/// </summary>
public bool CannotRegisterInStaticConstructor { get; init; }

/// <summary>
/// Whether this proxy needs ACW support (RegisterNatives + UCO wrappers + IAndroidCallableWrapper).
/// </summary>
Expand All @@ -166,7 +173,7 @@ sealed class JavaPeerProxyData
/// <summary>
/// A cross-assembly type reference (assembly name + full managed type name).
/// </summary>
sealed record TypeRefData
public sealed record TypeRefData
{
/// <summary>
/// Full managed type name, e.g., "Android.App.Activity" or "MyApp.Outer+Inner".
Expand All @@ -177,11 +184,19 @@ sealed record TypeRefData
/// Assembly containing the type, e.g., "Mono.Android".
/// </summary>
public required string AssemblyName { get; init; }

/// <summary>
/// True if this type — or, for array types, the element type — is an enum.
/// Used by the IL emitter to encode the type as <c>ELEMENT_TYPE_VALUETYPE</c>
/// rather than <c>ELEMENT_TYPE_CLASS</c> in member references and signatures.
/// </summary>
public bool IsEnum { get; init; }
}

/// <summary>
/// An [UnmanagedCallersOnly] static wrapper for a marshal method.
/// Body: load all args → call n_* callback → ret.
/// Body: either forward to an existing n_* callback or dispatch directly to the
/// managed export target when the trimmable path can avoid dynamic callback generation.
/// </summary>
sealed record UcoMethodData
{
Expand All @@ -191,7 +206,7 @@ sealed record UcoMethodData
public required string WrapperName { get; init; }

/// <summary>
/// Name of the n_* callback to call, e.g., "n_OnCreate".
/// Java/JNI-visible native method name, e.g., "n_OnCreate".
/// </summary>
public required string CallbackMethodName { get; init; }

Expand All @@ -204,6 +219,53 @@ sealed record UcoMethodData
/// JNI method signature, e.g., "(Landroid/os/Bundle;)V". Used to determine CLR parameter types.
/// </summary>
public required string JniSignature { get; init; }

/// <summary>
/// Optional [Export]-only metadata for wrappers that dispatch directly to the
/// managed export target instead of forwarding to a generated n_* callback.
/// </summary>
public ExportMethodDispatchData? ExportMethodDispatch { get; init; }

/// <summary>
/// True when this wrapper performs the static [Export] direct-dispatch path.
/// </summary>
public bool UsesExportMethodDispatch => ExportMethodDispatch != null;
}

sealed record ExportMethodDispatchData
{
/// <summary>
/// Managed method name on the callback type that should be invoked for [Export].
/// </summary>
public required string ManagedMethodName { get; init; }

/// <summary>
/// Managed parameter types for the target method, including the defining assembly.
/// </summary>
public IReadOnlyList<TypeRefData> ParameterTypes { get; init; } = [];

/// <summary>
/// Per-parameter [ExportParameter] kinds for legacy callback marshalling.
/// </summary>
public IReadOnlyList<ExportParameterKindInfo> ParameterKinds { get; init; } = [];

/// <summary>
/// Managed return type for the target method, including the defining assembly.
/// </summary>
public TypeRefData ReturnType { get; init; } = new () {
ManagedTypeName = "System.Void",
AssemblyName = "System.Runtime",
};

/// <summary>
/// [ExportParameter] kind applied to the return value, if any.
/// </summary>
public ExportParameterKindInfo ReturnKind { get; init; }

/// <summary>
/// Whether the managed target method is static.
/// </summary>
public bool IsStatic { get; init; }
}

/// <summary>
Expand All @@ -228,6 +290,24 @@ sealed record UcoConstructorData
/// JNI constructor signature, e.g., "(Landroid/content/Context;)V". Used for RegisterNatives registration.
/// </summary>
public required string JniSignature { get; init; }

/// <summary>
/// <see langword="true"/> when the UCO codegen can statically prove the managed
/// type defines a matching user-visible ctor with this signature. When
/// <see langword="false"/>, the codegen must use the legacy activation-ctor
/// `(IntPtr, JniHandleOwnership)` path instead of emitting a member ref to
/// a (potentially non-existent) user ctor.
/// </summary>
public required bool HasMatchingManagedCtor { get; init; }

/// <summary>
/// Managed parameter types of the matching user-visible ctor, in declaration
/// order. Empty for `()V`. Non-empty when <see cref="HasMatchingManagedCtor"/>
/// is <see langword="true"/> and the ctor takes parameters; the emitter uses
/// this to build the member ref signature and to marshal each JNI argument
/// to the corresponding managed type before calling the user ctor.
/// </summary>
public IReadOnlyList<TypeRefData> ManagedParameterTypes { get; init; } = [];
}

/// <summary>
Expand Down
Loading