Skip to content

Commit 0c5365e

Browse files
committed
Add generator model types and scanner enrichment for JCW/UCO generation
Add JniParameterInfo, JavaConstructorInfo, and additional properties to MarshalMethodInfo and JavaPeerInfo that generators require (JniReturnType, NativeCallbackName, Parameters, JavaConstructors, ManagedTypeNamespace, ManagedTypeShortName). Extend JniSignatureHelper with raw type string parsing. Enrich scanner output with these derived fields.
1 parent 850c594 commit 0c5365e

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed

src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JniSignatureHelper.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,26 @@ public static List<JniParamKind> ParseParameterTypes (string jniSignature)
3434
return result;
3535
}
3636

37+
/// <summary>Parses the raw JNI type descriptor strings from a JNI method signature.</summary>
38+
public static List<string> ParseParameterTypeStrings (string jniSignature)
39+
{
40+
var result = new List<string> ();
41+
int i = 1; // skip opening '('
42+
while (i < jniSignature.Length && jniSignature [i] != ')') {
43+
int start = i;
44+
SkipSingleType (jniSignature, ref i);
45+
result.Add (jniSignature.Substring (start, i - start));
46+
}
47+
return result;
48+
}
49+
50+
/// <summary>Extracts the return type descriptor from a JNI method signature.</summary>
51+
public static string ParseReturnTypeString (string jniSignature)
52+
{
53+
int i = jniSignature.IndexOf (')') + 1;
54+
return jniSignature.Substring (i);
55+
}
56+
3757
/// <summary>Parses the return type from a JNI method signature.</summary>
3858
public static JniParamKind ParseReturnType (string jniSignature)
3959
{
@@ -65,6 +85,25 @@ static JniParamKind ParseSingleType (string sig, ref int i)
6585
}
6686
}
6787

88+
static void SkipSingleType (string sig, ref int i)
89+
{
90+
switch (sig [i]) {
91+
case 'V': case 'Z': case 'B': case 'C': case 'S':
92+
case 'I': case 'J': case 'F': case 'D':
93+
i++;
94+
break;
95+
case 'L':
96+
i = sig.IndexOf (';', i) + 1;
97+
break;
98+
case '[':
99+
i++;
100+
SkipSingleType (sig, ref i);
101+
break;
102+
default:
103+
throw new ArgumentException ($"Unknown JNI type character '{sig [i]}' in '{sig}' at index {i}");
104+
}
105+
}
106+
68107
/// <summary>Encodes the CLR type for a JNI parameter kind into a signature type encoder.</summary>
69108
public static void EncodeClrType (SignatureTypeEncoder encoder, JniParamKind kind)
70109
{

src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerInfo.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ sealed class JavaPeerInfo
2828
/// </summary>
2929
public string ManagedTypeName { get; set; } = "";
3030

31+
/// <summary>
32+
/// Managed type namespace, e.g., "Android.App".
33+
/// </summary>
34+
public string ManagedTypeNamespace { get; set; } = "";
35+
36+
/// <summary>
37+
/// Managed type short name (without namespace), e.g., "Activity".
38+
/// </summary>
39+
public string ManagedTypeShortName { get; set; } = "";
40+
3141
/// <summary>
3242
/// Assembly name the type belongs to, e.g., "Mono.Android".
3343
/// </summary>
@@ -70,6 +80,12 @@ sealed class JavaPeerInfo
7080
/// </summary>
7181
public IReadOnlyList<MarshalMethodInfo> MarshalMethods { get; set; } = Array.Empty<MarshalMethodInfo> ();
7282

83+
/// <summary>
84+
/// Java constructors to emit in the JCW .java file.
85+
/// Each has a JNI signature and an ordinal index for the nctor_N native method.
86+
/// </summary>
87+
public IReadOnlyList<JavaConstructorInfo> JavaConstructors { get; set; } = Array.Empty<JavaConstructorInfo> ();
88+
7389
/// <summary>
7490
/// Information about the activation constructor for this type.
7591
/// May reference a base type's constructor if the type doesn't define its own.
@@ -119,6 +135,33 @@ sealed class MarshalMethodInfo
119135
/// </summary>
120136
public string ManagedMethodName { get; set; } = "";
121137

138+
/// <summary>
139+
/// Full name of the type that declares the managed method (may be a base type).
140+
/// </summary>
141+
public string DeclaringTypeName { get; set; } = "";
142+
143+
/// <summary>
144+
/// Assembly name of the type that declares the managed method.
145+
/// Needed for cross-assembly UCO wrapper generation.
146+
/// </summary>
147+
public string DeclaringAssemblyName { get; set; } = "";
148+
149+
/// <summary>
150+
/// The native callback method name, e.g., "n_onCreate".
151+
/// This is the actual method the UCO wrapper delegates to.
152+
/// </summary>
153+
public string NativeCallbackName { get; set; } = "";
154+
155+
/// <summary>
156+
/// JNI parameter types for UCO generation.
157+
/// </summary>
158+
public IReadOnlyList<JniParameterInfo> Parameters { get; set; } = Array.Empty<JniParameterInfo> ();
159+
160+
/// <summary>
161+
/// JNI return type descriptor, e.g., "V", "Landroid/os/Bundle;".
162+
/// </summary>
163+
public string JniReturnType { get; set; } = "";
164+
122165
/// <summary>
123166
/// True if this is a constructor registration.
124167
/// </summary>
@@ -137,6 +180,50 @@ sealed class MarshalMethodInfo
137180
public string? SuperArgumentsString { get; set; }
138181
}
139182

183+
/// <summary>
184+
/// Describes a JNI parameter for UCO method generation.
185+
/// </summary>
186+
sealed class JniParameterInfo
187+
{
188+
/// <summary>
189+
/// JNI type descriptor, e.g., "Landroid/os/Bundle;", "I", "Z".
190+
/// </summary>
191+
public string JniType { get; set; } = "";
192+
193+
/// <summary>
194+
/// Managed parameter type name, e.g., "Android.OS.Bundle", "System.Int32".
195+
/// </summary>
196+
public string ManagedType { get; set; } = "";
197+
}
198+
199+
/// <summary>
200+
/// Describes a Java constructor to emit in the JCW .java source file.
201+
/// </summary>
202+
sealed class JavaConstructorInfo
203+
{
204+
/// <summary>
205+
/// JNI constructor signature, e.g., "(Landroid/content/Context;)V".
206+
/// </summary>
207+
public string JniSignature { get; set; } = "";
208+
209+
/// <summary>
210+
/// Ordinal index for the native constructor method (nctor_0, nctor_1, ...).
211+
/// </summary>
212+
public int ConstructorIndex { get; set; }
213+
214+
/// <summary>
215+
/// JNI parameter types parsed from the signature.
216+
/// Used to generate the Java constructor parameter list.
217+
/// </summary>
218+
public IReadOnlyList<JniParameterInfo> Parameters { get; set; } = Array.Empty<JniParameterInfo> ();
219+
220+
/// <summary>
221+
/// For [Export] constructors: super constructor arguments string.
222+
/// Null for [Register] constructors.
223+
/// </summary>
224+
public string? SuperArgumentsString { get; set; }
225+
}
226+
140227
/// <summary>
141228
/// Describes how to call the activation constructor for a Java peer type.
142229
/// </summary>

src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ void ScanAssembly (AssemblyIndex index, Dictionary<string, JavaPeerInfo> results
214214
JavaName = jniName,
215215
CompatJniName = compatJniName,
216216
ManagedTypeName = fullName,
217+
ManagedTypeNamespace = ExtractNamespace (fullName),
218+
ManagedTypeShortName = ExtractShortName (fullName),
217219
AssemblyName = index.AssemblyName,
218220
BaseJavaName = baseJavaName,
219221
ImplementedInterfaceJavaNames = implementedInterfaces,
@@ -222,6 +224,7 @@ void ScanAssembly (AssemblyIndex index, Dictionary<string, JavaPeerInfo> results
222224
DoNotGenerateAcw = doNotGenerateAcw,
223225
IsUnconditional = isUnconditional,
224226
MarshalMethods = marshalMethods,
227+
JavaConstructors = BuildJavaConstructors (marshalMethods),
225228
ActivationCtor = activationCtor,
226229
InvokerTypeName = invokerTypeName,
227230
IsGenericDefinition = isGenericDefinition,
@@ -276,6 +279,9 @@ static void AddMarshalMethod (List<MarshalMethodInfo> methods, RegisterInfo regi
276279
JniSignature = registerInfo.Signature ?? "()V",
277280
Connector = registerInfo.Connector,
278281
ManagedMethodName = index.Reader.GetString (methodDef.Name),
282+
NativeCallbackName = "n_" + index.Reader.GetString (methodDef.Name),
283+
JniReturnType = JniSignatureHelper.ParseReturnTypeString (registerInfo.Signature ?? "()V"),
284+
Parameters = ParseJniParameters (registerInfo.Signature ?? "()V"),
279285
IsConstructor = registerInfo.JniName == "<init>" || registerInfo.JniName == ".ctor",
280286
ThrownNames = registerInfo.ThrownNames,
281287
SuperArgumentsString = registerInfo.SuperArgumentsString,
@@ -741,4 +747,45 @@ static string GetCrc64PackageName (string ns, string assemblyName)
741747
var hash = System.IO.Hashing.Crc64.Hash (data);
742748
return "crc64" + BitConverter.ToString (hash).Replace ("-", "").ToLowerInvariant ();
743749
}
750+
751+
static string ExtractNamespace (string fullName)
752+
{
753+
int lastDot = fullName.LastIndexOf ('.');
754+
return lastDot >= 0 ? fullName.Substring (0, lastDot) : "";
755+
}
756+
757+
static string ExtractShortName (string fullName)
758+
{
759+
int lastDot = fullName.LastIndexOf ('.');
760+
return lastDot >= 0 ? fullName.Substring (lastDot + 1) : fullName;
761+
}
762+
763+
static List<JniParameterInfo> ParseJniParameters (string jniSignature)
764+
{
765+
var typeStrings = JniSignatureHelper.ParseParameterTypeStrings (jniSignature);
766+
var result = new List<JniParameterInfo> (typeStrings.Count);
767+
foreach (var t in typeStrings) {
768+
result.Add (new JniParameterInfo { JniType = t });
769+
}
770+
return result;
771+
}
772+
773+
static List<JavaConstructorInfo> BuildJavaConstructors (List<MarshalMethodInfo> marshalMethods)
774+
{
775+
var ctors = new List<JavaConstructorInfo> ();
776+
int ctorIndex = 0;
777+
foreach (var mm in marshalMethods) {
778+
if (!mm.IsConstructor) {
779+
continue;
780+
}
781+
ctors.Add (new JavaConstructorInfo {
782+
JniSignature = mm.JniSignature,
783+
ConstructorIndex = ctorIndex,
784+
Parameters = mm.Parameters,
785+
SuperArgumentsString = mm.SuperArgumentsString,
786+
});
787+
ctorIndex++;
788+
}
789+
return ctors;
790+
}
744791
}

0 commit comments

Comments
 (0)