@@ -308,7 +308,7 @@ void ScanAssembly (AssemblyIndex index, Dictionary<string, JavaPeerInfo> results
308308 return ( methods , exportFields ) ;
309309 }
310310
311- static void AddMarshalMethod ( List < MarshalMethodInfo > methods , RegisterInfo registerInfo , MethodDefinition methodDef , AssemblyIndex index )
311+ void AddMarshalMethod ( List < MarshalMethodInfo > methods , RegisterInfo registerInfo , MethodDefinition methodDef , AssemblyIndex index )
312312 {
313313 // Skip methods that are just the JNI name (type-level [Register])
314314 if ( registerInfo . Signature == null && registerInfo . Connector == null ) {
@@ -328,10 +328,10 @@ static void AddMarshalMethod (List<MarshalMethodInfo> methods, RegisterInfo regi
328328 if ( registerInfo . Connector == null || isConstructor ) {
329329 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
330330 for ( int i = 0 ; i < parameters . Count && i < sig . ParameterTypes . Length ; i ++ ) {
331- parameters [ i ] . ManagedType = ManagedTypeToAssemblyQualifiedName ( sig . ParameterTypes [ i ] ) ;
331+ parameters [ i ] . ManagedType = ManagedTypeToAssemblyQualifiedName ( sig . ParameterTypes [ i ] , index ) ;
332332 }
333333 if ( sig . ReturnType != "System.Void" ) {
334- managedReturnType = ManagedTypeToAssemblyQualifiedName ( sig . ReturnType ) ;
334+ managedReturnType = ManagedTypeToAssemblyQualifiedName ( sig . ReturnType , index ) ;
335335 }
336336 }
337337
@@ -409,7 +409,7 @@ List<string> ResolveImplementedInterfaceJavaNames (TypeDefinition typeDef, Assem
409409 return null ;
410410 }
411411
412- static RegisterInfo ParseExportAttribute ( CustomAttribute ca , MethodDefinition methodDef , AssemblyIndex index )
412+ RegisterInfo ParseExportAttribute ( CustomAttribute ca , MethodDefinition methodDef , AssemblyIndex index )
413413 {
414414 var value = ca . DecodeValue ( index . customAttributeTypeProvider ) ;
415415
@@ -439,7 +439,7 @@ static RegisterInfo ParseExportAttribute (CustomAttribute ca, MethodDefinition m
439439
440440 // Build JNI signature from method signature
441441 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
442- var jniSig = BuildJniSignatureFromManaged ( sig ) ;
442+ var jniSig = BuildJniSignatureFromManaged ( sig , index ) ;
443443
444444 return new RegisterInfo ( exportName , jniSig , null , false ,
445445 thrownNames : thrownNames , superArgumentsString : superArguments ) ;
@@ -449,11 +449,11 @@ static RegisterInfo ParseExportAttribute (CustomAttribute ca, MethodDefinition m
449449 /// Creates a RegisterInfo for an [ExportField] method.
450450 /// The method is registered like [Export] (Connector = null) so it gets a full marshal body.
451451 /// </summary>
452- static RegisterInfo ParseExportFieldAsRegisterInfo ( MethodDefinition methodDef , AssemblyIndex index )
452+ RegisterInfo ParseExportFieldAsRegisterInfo ( MethodDefinition methodDef , AssemblyIndex index )
453453 {
454454 var methodName = index . Reader . GetString ( methodDef . Name ) ;
455455 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
456- var jniSig = BuildJniSignatureFromManaged ( sig ) ;
456+ var jniSig = BuildJniSignatureFromManaged ( sig , index ) ;
457457 return new RegisterInfo ( methodName , jniSig , null , false ) ;
458458 }
459459
@@ -497,19 +497,19 @@ static RegisterInfo ParseExportFieldAsRegisterInfo (MethodDefinition methodDef,
497497 return null ;
498498 }
499499
500- static string BuildJniSignatureFromManaged ( MethodSignature < string > sig )
500+ string BuildJniSignatureFromManaged ( MethodSignature < string > sig , AssemblyIndex index )
501501 {
502502 var sb = new System . Text . StringBuilder ( ) ;
503503 sb . Append ( '(' ) ;
504504 foreach ( var param in sig . ParameterTypes ) {
505- sb . Append ( ManagedTypeToJniDescriptor ( param ) ) ;
505+ sb . Append ( ManagedTypeToJniDescriptor ( param , index ) ) ;
506506 }
507507 sb . Append ( ')' ) ;
508- sb . Append ( ManagedTypeToJniDescriptor ( sig . ReturnType ) ) ;
508+ sb . Append ( ManagedTypeToJniDescriptor ( sig . ReturnType , index ) ) ;
509509 return sb . ToString ( ) ;
510510 }
511511
512- static string ManagedTypeToJniDescriptor ( string managedType )
512+ string ManagedTypeToJniDescriptor ( string managedType , AssemblyIndex index )
513513 {
514514 switch ( managedType ) {
515515 case "System.Void" : return "V" ;
@@ -526,9 +526,17 @@ static string ManagedTypeToJniDescriptor (string managedType)
526526 case "System.Single" : return "F" ;
527527 case "System.Double" : return "D" ;
528528 case "System.String" : return "Ljava/lang/String;" ;
529+ case "Java.Lang.ICharSequence" : return "Ljava/lang/CharSequence;" ;
529530 default :
530531 if ( managedType . EndsWith ( "[]" ) ) {
531- return "[" + ManagedTypeToJniDescriptor ( managedType . Substring ( 0 , managedType . Length - 2 ) ) ;
532+ return "[" + ManagedTypeToJniDescriptor ( managedType . Substring ( 0 , managedType . Length - 2 ) , index ) ;
533+ }
534+ if ( IsEnumManagedType ( managedType , index ) ) {
535+ return "I" ;
536+ }
537+ var jniName = ResolveManagedTypeJniName ( managedType , index ) ;
538+ if ( ! string . IsNullOrEmpty ( jniName ) ) {
539+ return "L" + jniName + ";" ;
532540 }
533541 return "Ljava/lang/Object;" ;
534542 }
@@ -538,8 +546,12 @@ static string ManagedTypeToJniDescriptor (string managedType)
538546 /// Maps a managed type name (from SignatureTypeProvider) to an assembly-qualified name
539547 /// like "System.Int32, System.Private.CoreLib" used in TypeManager.Activate calls.
540548 /// </summary>
541- static string ManagedTypeToAssemblyQualifiedName ( string managedType )
549+ string ManagedTypeToAssemblyQualifiedName ( string managedType , AssemblyIndex index )
542550 {
551+ if ( managedType . IndexOf ( ", " , StringComparison . Ordinal ) >= 0 ) {
552+ return managedType ;
553+ }
554+
543555 // BCL types all live in System.Private.CoreLib
544556 switch ( managedType ) {
545557 case "System.Void" :
@@ -561,11 +573,131 @@ static string ManagedTypeToAssemblyQualifiedName (string managedType)
561573 case "System.UIntPtr" :
562574 return managedType + ", System.Private.CoreLib" ;
563575 default :
564- // For non-BCL types, we don't know the assembly at this point.
565- // This is a best-effort mapping; full assembly resolution for
566- // arbitrary types is a follow-up.
567- return managedType ;
576+ // Best-effort assembly resolution across loaded assemblies.
577+ var assemblyName = ResolveManagedTypeAssemblyName ( managedType , index ) ;
578+ return assemblyName != null ? managedType + ", " + assemblyName : managedType ;
579+ }
580+ }
581+
582+ string ? ResolveManagedTypeAssemblyName ( string managedType , AssemblyIndex index )
583+ {
584+ string typeName = StripManagedTypeDecorations ( managedType ) ;
585+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
586+ return null ; // generic method/type parameter
587+ }
588+
589+ if ( IsBclTypeName ( typeName ) ) {
590+ return "System.Private.CoreLib" ;
591+ }
592+
593+ if ( TryResolveManagedTypeDefinition ( typeName , index , out _ , out var resolvedIndex ) ) {
594+ return resolvedIndex . AssemblyName ;
595+ }
596+
597+ return index . AssemblyName ;
598+ }
599+
600+ bool IsEnumManagedType ( string managedType , AssemblyIndex index )
601+ {
602+ string typeName = StripManagedTypeDecorations ( managedType ) ;
603+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
604+ return false ;
605+ }
606+
607+ if ( ! TryResolveManagedTypeDefinition ( typeName , index , out var handle , out var resolvedIndex ) ) {
608+ return false ;
609+ }
610+
611+ var typeDef = resolvedIndex . Reader . GetTypeDefinition ( handle ) ;
612+ if ( typeDef . BaseType . Kind == HandleKind . TypeReference ) {
613+ var ( baseTypeName , _) = ResolveTypeReference ( ( TypeReferenceHandle ) typeDef . BaseType , resolvedIndex ) ;
614+ return baseTypeName == "System.Enum" ;
615+ }
616+ if ( typeDef . BaseType . Kind == HandleKind . TypeDefinition ) {
617+ var baseTypeDef = resolvedIndex . Reader . GetTypeDefinition ( ( TypeDefinitionHandle ) typeDef . BaseType ) ;
618+ return AssemblyIndex . GetFullName ( baseTypeDef , resolvedIndex . Reader ) == "System.Enum" ;
619+ }
620+ return false ;
621+ }
622+
623+ string ? ResolveManagedTypeJniName ( string managedType , AssemblyIndex index )
624+ {
625+ string typeName = StripManagedTypeDecorations ( managedType ) ;
626+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
627+ return null ;
628+ }
629+
630+ if ( ! TryResolveManagedTypeDefinition ( typeName , index , out var handle , out var resolvedIndex ) ) {
631+ return null ;
632+ }
633+
634+ if ( resolvedIndex . RegisterInfoByType . TryGetValue ( handle , out var regInfo ) &&
635+ ! string . IsNullOrEmpty ( regInfo . JniName ) ) {
636+ return regInfo . JniName ;
637+ }
638+
639+ return null ;
640+ }
641+
642+ bool TryResolveManagedTypeDefinition ( string managedTypeName , AssemblyIndex index , out TypeDefinitionHandle handle , out AssemblyIndex resolvedIndex )
643+ {
644+ if ( TryResolveType ( managedTypeName , index . AssemblyName , out handle , out resolvedIndex ) ) {
645+ return true ;
646+ }
647+
648+ foreach ( var candidate in assemblyCache . Values ) {
649+ if ( candidate . TypesByFullName . TryGetValue ( managedTypeName , out handle ) ) {
650+ resolvedIndex = candidate ;
651+ return true ;
652+ }
653+ }
654+
655+ handle = default ;
656+ resolvedIndex = null ! ;
657+ return false ;
658+ }
659+
660+ static bool IsBclTypeName ( string managedTypeName )
661+ {
662+ switch ( managedTypeName ) {
663+ case "System.Void" :
664+ case "System.Boolean" :
665+ case "System.Byte" :
666+ case "System.SByte" :
667+ case "System.Char" :
668+ case "System.Int16" :
669+ case "System.UInt16" :
670+ case "System.Int32" :
671+ case "System.UInt32" :
672+ case "System.Int64" :
673+ case "System.UInt64" :
674+ case "System.Single" :
675+ case "System.Double" :
676+ case "System.String" :
677+ case "System.Object" :
678+ case "System.IntPtr" :
679+ case "System.UIntPtr" :
680+ return true ;
681+ default :
682+ return false ;
683+ }
684+ }
685+
686+ static string StripManagedTypeDecorations ( string managedType )
687+ {
688+ string result = managedType ;
689+ while ( result . EndsWith ( "[]" , StringComparison . Ordinal ) ||
690+ result . EndsWith ( "&" , StringComparison . Ordinal ) ||
691+ result . EndsWith ( "*" , StringComparison . Ordinal ) ) {
692+ result = result . Substring ( 0 , result . Length - ( result . EndsWith ( "[]" , StringComparison . Ordinal ) ? 2 : 1 ) ) ;
693+ }
694+
695+ int genericStart = result . IndexOf ( '<' ) ;
696+ if ( genericStart >= 0 ) {
697+ result = result . Substring ( 0 , genericStart ) ;
568698 }
699+
700+ return result ;
569701 }
570702
571703 ActivationCtorInfo ? ResolveActivationCtor ( string typeName , TypeDefinition typeDef , AssemblyIndex index )
0 commit comments