@@ -304,7 +304,7 @@ void ScanAssembly (AssemblyIndex index, Dictionary<string, JavaPeerInfo> results
304304 return ( methods , exportFields ) ;
305305 }
306306
307- static void AddMarshalMethod ( List < MarshalMethodInfo > methods , RegisterInfo registerInfo , MethodDefinition methodDef , AssemblyIndex index )
307+ void AddMarshalMethod ( List < MarshalMethodInfo > methods , RegisterInfo registerInfo , MethodDefinition methodDef , AssemblyIndex index )
308308 {
309309 // Skip methods that are just the JNI name (type-level [Register])
310310 if ( registerInfo . Signature == null && registerInfo . Connector == null ) {
@@ -324,10 +324,10 @@ static void AddMarshalMethod (List<MarshalMethodInfo> methods, RegisterInfo regi
324324 if ( registerInfo . Connector == null || isConstructor ) {
325325 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
326326 for ( int i = 0 ; i < parameters . Count && i < sig . ParameterTypes . Length ; i ++ ) {
327- parameters [ i ] . ManagedType = ManagedTypeToAssemblyQualifiedName ( sig . ParameterTypes [ i ] ) ;
327+ parameters [ i ] . ManagedType = ManagedTypeToAssemblyQualifiedName ( sig . ParameterTypes [ i ] , index ) ;
328328 }
329329 if ( sig . ReturnType != "System.Void" ) {
330- managedReturnType = ManagedTypeToAssemblyQualifiedName ( sig . ReturnType ) ;
330+ managedReturnType = ManagedTypeToAssemblyQualifiedName ( sig . ReturnType , index ) ;
331331 }
332332 }
333333 methods . Add ( new MarshalMethodInfo {
@@ -404,7 +404,7 @@ List<string> ResolveImplementedInterfaceJavaNames (TypeDefinition typeDef, Assem
404404 return null ;
405405 }
406406
407- static RegisterInfo ParseExportAttribute ( CustomAttribute ca , MethodDefinition methodDef , AssemblyIndex index )
407+ RegisterInfo ParseExportAttribute ( CustomAttribute ca , MethodDefinition methodDef , AssemblyIndex index )
408408 {
409409 var value = ca . DecodeValue ( index . customAttributeTypeProvider ) ;
410410
@@ -434,7 +434,7 @@ static RegisterInfo ParseExportAttribute (CustomAttribute ca, MethodDefinition m
434434
435435 // Build JNI signature from method signature
436436 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
437- var jniSig = BuildJniSignatureFromManaged ( sig ) ;
437+ var jniSig = BuildJniSignatureFromManaged ( sig , index ) ;
438438
439439 return new RegisterInfo ( exportName , jniSig , null , false ,
440440 thrownNames : thrownNames , superArgumentsString : superArguments ) ;
@@ -444,11 +444,11 @@ static RegisterInfo ParseExportAttribute (CustomAttribute ca, MethodDefinition m
444444 /// Creates a RegisterInfo for an [ExportField] method.
445445 /// The method is registered like [Export] (Connector = null) so it gets a full marshal body.
446446 /// </summary>
447- static RegisterInfo ParseExportFieldAsRegisterInfo ( MethodDefinition methodDef , AssemblyIndex index )
447+ RegisterInfo ParseExportFieldAsRegisterInfo ( MethodDefinition methodDef , AssemblyIndex index )
448448 {
449449 var methodName = index . Reader . GetString ( methodDef . Name ) ;
450450 var sig = methodDef . DecodeSignature ( SignatureTypeProvider . Instance , genericContext : default ) ;
451- var jniSig = BuildJniSignatureFromManaged ( sig ) ;
451+ var jniSig = BuildJniSignatureFromManaged ( sig , index ) ;
452452 return new RegisterInfo ( methodName , jniSig , null , false ) ;
453453 }
454454
@@ -492,19 +492,19 @@ static RegisterInfo ParseExportFieldAsRegisterInfo (MethodDefinition methodDef,
492492 return null ;
493493 }
494494
495- static string BuildJniSignatureFromManaged ( MethodSignature < string > sig )
495+ string BuildJniSignatureFromManaged ( MethodSignature < string > sig , AssemblyIndex index )
496496 {
497497 var sb = new System . Text . StringBuilder ( ) ;
498498 sb . Append ( '(' ) ;
499499 foreach ( var param in sig . ParameterTypes ) {
500- sb . Append ( ManagedTypeToJniDescriptor ( param ) ) ;
500+ sb . Append ( ManagedTypeToJniDescriptor ( param , index ) ) ;
501501 }
502502 sb . Append ( ')' ) ;
503- sb . Append ( ManagedTypeToJniDescriptor ( sig . ReturnType ) ) ;
503+ sb . Append ( ManagedTypeToJniDescriptor ( sig . ReturnType , index ) ) ;
504504 return sb . ToString ( ) ;
505505 }
506506
507- static string ManagedTypeToJniDescriptor ( string managedType )
507+ string ManagedTypeToJniDescriptor ( string managedType , AssemblyIndex index )
508508 {
509509 switch ( managedType ) {
510510 case "System.Void" : return "V" ;
@@ -521,9 +521,17 @@ static string ManagedTypeToJniDescriptor (string managedType)
521521 case "System.Single" : return "F" ;
522522 case "System.Double" : return "D" ;
523523 case "System.String" : return "Ljava/lang/String;" ;
524+ case "Java.Lang.ICharSequence" : return "Ljava/lang/CharSequence;" ;
524525 default :
525526 if ( managedType . EndsWith ( "[]" ) ) {
526- return "[" + ManagedTypeToJniDescriptor ( managedType . Substring ( 0 , managedType . Length - 2 ) ) ;
527+ return "[" + ManagedTypeToJniDescriptor ( managedType . Substring ( 0 , managedType . Length - 2 ) , index ) ;
528+ }
529+ if ( IsEnumManagedType ( managedType , index ) ) {
530+ return "I" ;
531+ }
532+ var jniName = ResolveManagedTypeJniName ( managedType , index ) ;
533+ if ( ! string . IsNullOrEmpty ( jniName ) ) {
534+ return "L" + jniName + ";" ;
527535 }
528536 return "Ljava/lang/Object;" ;
529537 }
@@ -533,8 +541,12 @@ static string ManagedTypeToJniDescriptor (string managedType)
533541 /// Maps a managed type name (from SignatureTypeProvider) to an assembly-qualified name
534542 /// like "System.Int32, System.Private.CoreLib" used in TypeManager.Activate calls.
535543 /// </summary>
536- static string ManagedTypeToAssemblyQualifiedName ( string managedType )
544+ string ManagedTypeToAssemblyQualifiedName ( string managedType , AssemblyIndex index )
537545 {
546+ if ( managedType . IndexOf ( ", " , StringComparison . Ordinal ) >= 0 ) {
547+ return managedType ;
548+ }
549+
538550 // BCL types all live in System.Private.CoreLib
539551 switch ( managedType ) {
540552 case "System.Void" :
@@ -556,11 +568,131 @@ static string ManagedTypeToAssemblyQualifiedName (string managedType)
556568 case "System.UIntPtr" :
557569 return managedType + ", System.Private.CoreLib" ;
558570 default :
559- // For non-BCL types, we don't know the assembly at this point.
560- // This is a best-effort mapping; full assembly resolution for
561- // arbitrary types is a follow-up.
562- return managedType ;
571+ // Best-effort assembly resolution across loaded assemblies.
572+ var assemblyName = ResolveManagedTypeAssemblyName ( managedType , index ) ;
573+ return assemblyName != null ? managedType + ", " + assemblyName : managedType ;
574+ }
575+ }
576+
577+ string ? ResolveManagedTypeAssemblyName ( string managedType , AssemblyIndex index )
578+ {
579+ string typeName = StripManagedTypeDecorations ( managedType ) ;
580+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
581+ return null ; // generic method/type parameter
582+ }
583+
584+ if ( IsBclTypeName ( typeName ) ) {
585+ return "System.Private.CoreLib" ;
586+ }
587+
588+ if ( TryResolveManagedTypeDefinition ( typeName , index , out _ , out var resolvedIndex ) ) {
589+ return resolvedIndex . AssemblyName ;
590+ }
591+
592+ return index . AssemblyName ;
593+ }
594+
595+ bool IsEnumManagedType ( string managedType , AssemblyIndex index )
596+ {
597+ string typeName = StripManagedTypeDecorations ( managedType ) ;
598+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
599+ return false ;
600+ }
601+
602+ if ( ! TryResolveManagedTypeDefinition ( typeName , index , out var handle , out var resolvedIndex ) ) {
603+ return false ;
604+ }
605+
606+ var typeDef = resolvedIndex . Reader . GetTypeDefinition ( handle ) ;
607+ if ( typeDef . BaseType . Kind == HandleKind . TypeReference ) {
608+ var ( baseTypeName , _) = ResolveTypeReference ( ( TypeReferenceHandle ) typeDef . BaseType , resolvedIndex ) ;
609+ return baseTypeName == "System.Enum" ;
610+ }
611+ if ( typeDef . BaseType . Kind == HandleKind . TypeDefinition ) {
612+ var baseTypeDef = resolvedIndex . Reader . GetTypeDefinition ( ( TypeDefinitionHandle ) typeDef . BaseType ) ;
613+ return AssemblyIndex . GetFullName ( baseTypeDef , resolvedIndex . Reader ) == "System.Enum" ;
563614 }
615+ return false ;
616+ }
617+
618+ string ? ResolveManagedTypeJniName ( string managedType , AssemblyIndex index )
619+ {
620+ string typeName = StripManagedTypeDecorations ( managedType ) ;
621+ if ( typeName . Length == 0 || typeName [ 0 ] == '!' ) {
622+ return null ;
623+ }
624+
625+ if ( ! TryResolveManagedTypeDefinition ( typeName , index , out var handle , out var resolvedIndex ) ) {
626+ return null ;
627+ }
628+
629+ if ( resolvedIndex . RegisterInfoByType . TryGetValue ( handle , out var regInfo ) &&
630+ ! string . IsNullOrEmpty ( regInfo . JniName ) ) {
631+ return regInfo . JniName ;
632+ }
633+
634+ return null ;
635+ }
636+
637+ bool TryResolveManagedTypeDefinition ( string managedTypeName , AssemblyIndex index , out TypeDefinitionHandle handle , out AssemblyIndex resolvedIndex )
638+ {
639+ if ( TryResolveType ( managedTypeName , index . AssemblyName , out handle , out resolvedIndex ) ) {
640+ return true ;
641+ }
642+
643+ foreach ( var candidate in assemblyCache . Values ) {
644+ if ( candidate . TypesByFullName . TryGetValue ( managedTypeName , out handle ) ) {
645+ resolvedIndex = candidate ;
646+ return true ;
647+ }
648+ }
649+
650+ handle = default ;
651+ resolvedIndex = null ! ;
652+ return false ;
653+ }
654+
655+ static bool IsBclTypeName ( string managedTypeName )
656+ {
657+ switch ( managedTypeName ) {
658+ case "System.Void" :
659+ case "System.Boolean" :
660+ case "System.Byte" :
661+ case "System.SByte" :
662+ case "System.Char" :
663+ case "System.Int16" :
664+ case "System.UInt16" :
665+ case "System.Int32" :
666+ case "System.UInt32" :
667+ case "System.Int64" :
668+ case "System.UInt64" :
669+ case "System.Single" :
670+ case "System.Double" :
671+ case "System.String" :
672+ case "System.Object" :
673+ case "System.IntPtr" :
674+ case "System.UIntPtr" :
675+ return true ;
676+ default :
677+ return false ;
678+ }
679+ }
680+
681+ static string StripManagedTypeDecorations ( string managedType )
682+ {
683+ string result = managedType ;
684+ while ( result . EndsWith ( "[]" , StringComparison . Ordinal ) ||
685+ result . EndsWith ( "&" , StringComparison . Ordinal ) ||
686+ result . EndsWith ( "*" , StringComparison . Ordinal ) ) {
687+ result = result . Substring ( 0 , result . Length - ( result . EndsWith ( "[]" , StringComparison . Ordinal ) ? 2 : 1 ) ) ;
688+ }
689+
690+ int genericStart = result . IndexOf ( '<' ) ;
691+ if ( genericStart >= 0 ) {
692+ result = result . Substring ( 0 , genericStart ) ;
693+ }
694+
695+ return result ;
564696 }
565697
566698 ActivationCtorInfo ? ResolveActivationCtor ( string typeName , TypeDefinition typeDef , AssemblyIndex index )
@@ -872,47 +1004,6 @@ static List<JniParameterInfo> ParseJniParameters (string jniSignature)
8721004 return result ;
8731005 }
8741006
875- static List < JavaConstructorInfo > BuildJavaConstructors ( List < MarshalMethodInfo > marshalMethods )
876- {
877- var ctors = new List < JavaConstructorInfo > ( ) ;
878- int ctorIndex = 0 ;
879- foreach ( var mm in marshalMethods ) {
880- if ( ! mm . IsConstructor ) {
881- continue ;
882- }
883- ctors . Add ( new JavaConstructorInfo {
884- JniSignature = mm . JniSignature ,
885- ConstructorIndex = ctorIndex ,
886- Parameters = mm . Parameters ,
887- SuperArgumentsString = mm . SuperArgumentsString ,
888- } ) ;
889- ctorIndex ++ ;
890- }
891- return ctors ;
892- }
893-
894- static string ExtractNamespace ( string fullName )
895- {
896- int lastDot = fullName . LastIndexOf ( '.' ) ;
897- return lastDot >= 0 ? fullName . Substring ( 0 , lastDot ) : "" ;
898- }
899-
900- static string ExtractShortName ( string fullName )
901- {
902- int lastDot = fullName . LastIndexOf ( '.' ) ;
903- return lastDot >= 0 ? fullName . Substring ( lastDot + 1 ) : fullName ;
904- }
905-
906- static List < JniParameterInfo > ParseJniParameters ( string jniSignature )
907- {
908- var typeStrings = JniSignatureHelper . ParseParameterTypeStrings ( jniSignature ) ;
909- var result = new List < JniParameterInfo > ( typeStrings . Count ) ;
910- foreach ( var t in typeStrings ) {
911- result . Add ( new JniParameterInfo { JniType = t } ) ;
912- }
913- return result ;
914- }
915-
9161007 static List < JavaConstructorInfo > BuildJavaConstructors ( List < MarshalMethodInfo > marshalMethods )
9171008 {
9181009 var ctors = new List < JavaConstructorInfo > ( ) ;
0 commit comments