2002-12-18 19:00:25 +03:00
/ *
2008-02-17 14:33:03 +03:00
Copyright ( C ) 2002 - 2008 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
Jeroen Frijters
jeroen @frijters . net
* /
using System ;
2005-12-07 12:06:32 +03:00
using System.Collections.Generic ;
2002-12-18 19:00:25 +03:00
using System.Reflection ;
2008-11-14 11:42:07 +03:00
#if IKVM_REF_EMIT
using IKVM.Reflection.Emit ;
#elif ! COMPACT_FRAMEWORK
2002-12-18 19:00:25 +03:00
using System.Reflection.Emit ;
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
using System.Diagnostics ;
2005-05-23 12:24:07 +04:00
using System.Security ;
using System.Security.Permissions ;
2004-09-09 15:17:55 +04:00
using IKVM.Attributes ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
namespace IKVM.Internal
2003-05-13 00:00:15 +04:00
{
2006-04-05 12:18:58 +04:00
struct ExModifiers
{
internal readonly Modifiers Modifiers ;
internal readonly bool IsInternal ;
internal ExModifiers ( Modifiers modifiers , bool isInternal )
{
this . Modifiers = modifiers ;
this . IsInternal = isInternal ;
}
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 11:13:49 +04:00
static class EmitHelper
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
private static MethodInfo objectToString = typeof ( object ) . GetMethod ( "ToString" , BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
2006-04-11 16:05:24 +04:00
private static MethodInfo verboseCastFailure = JVM . SafeGetEnvironmentVariable ( "IKVM_VERBOSE_CAST" ) = = null ? null : ByteCodeHelperMethods . VerboseCastFailure ;
2009-02-23 08:17:21 +03:00
private static MethodInfo getTypeHandle = typeof ( Type ) . GetMethod ( "GetTypeHandle" , BindingFlags . Public | BindingFlags . Static , null , new Type [ ] { typeof ( object ) } , null ) ;
private static MethodInfo get_Value = typeof ( RuntimeTypeHandle ) . GetMethod ( "get_Value" , BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
2005-12-07 12:06:32 +03:00
2008-06-03 16:10:07 +04:00
internal static void Throw ( CodeEmitter ilgen , string dottedClassName )
2005-06-01 13:49:30 +04:00
{
TypeWrapper exception = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( dottedClassName ) ;
MethodWrapper mw = exception . GetMethodWrapper ( "<init>" , "()V" , false ) ;
mw . Link ( ) ;
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Throw ) ;
}
2003-05-30 16:08:59 +04:00
2008-06-03 16:10:07 +04:00
internal static void Throw ( CodeEmitter ilgen , string dottedClassName , string message )
2005-06-01 13:49:30 +04:00
{
TypeWrapper exception = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( dottedClassName ) ;
ilgen . Emit ( OpCodes . Ldstr , message ) ;
MethodWrapper mw = exception . GetMethodWrapper ( "<init>" , "(Ljava.lang.String;)V" , false ) ;
mw . Link ( ) ;
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Throw ) ;
}
2008-06-03 16:10:07 +04:00
internal static void NullCheck ( CodeEmitter ilgen )
2005-06-01 13:49:30 +04:00
{
// I think this is the most efficient way to generate a NullReferenceException if the
// reference is null
ilgen . Emit ( OpCodes . Ldvirtftn , objectToString ) ;
2003-11-17 15:01:50 +03:00
ilgen . Emit ( OpCodes . Pop ) ;
}
2004-03-08 18:18:47 +03:00
2008-06-03 16:10:07 +04:00
internal static void Castclass ( CodeEmitter ilgen , Type type )
2005-06-01 13:49:30 +04:00
{
if ( verboseCastFailure ! = null )
{
LocalBuilder lb = ilgen . DeclareLocal ( typeof ( object ) ) ;
ilgen . Emit ( OpCodes . Stloc , lb ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Isinst , type ) ;
ilgen . Emit ( OpCodes . Dup ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel ok = ilgen . DefineLabel ( ) ;
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Brtrue_S , ok ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Brfalse_S , ok ) ; // handle null
ilgen . Emit ( OpCodes . Ldtoken , type ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Call , verboseCastFailure ) ;
ilgen . MarkLabel ( ok ) ;
}
else
{
ilgen . Emit ( OpCodes . Castclass , type ) ;
}
}
2005-02-11 17:46:58 +03:00
2005-06-01 13:49:30 +04:00
// This is basically the same as Castclass, except that it
// throws an IncompatibleClassChangeError on failure.
2008-06-03 16:10:07 +04:00
internal static void EmitAssertType ( CodeEmitter ilgen , Type type )
2005-02-11 17:46:58 +03:00
{
LocalBuilder lb = ilgen . DeclareLocal ( typeof ( object ) ) ;
ilgen . Emit ( OpCodes . Stloc , lb ) ;
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
ilgen . Emit ( OpCodes . Isinst , type ) ;
ilgen . Emit ( OpCodes . Dup ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel ok = ilgen . DefineLabel ( ) ;
2005-02-16 14:20:43 +03:00
ilgen . Emit ( OpCodes . Brtrue_S , ok ) ;
2005-02-11 17:46:58 +03:00
ilgen . Emit ( OpCodes . Ldloc , lb ) ;
2005-02-16 14:20:43 +03:00
ilgen . Emit ( OpCodes . Brfalse_S , ok ) ; // handle null
2005-06-01 13:49:30 +04:00
EmitHelper . Throw ( ilgen , "java.lang.IncompatibleClassChangeError" ) ;
2005-02-11 17:46:58 +03:00
ilgen . MarkLabel ( ok ) ;
}
2009-02-22 11:19:30 +03:00
internal static void GetTypeHandleValue ( CodeEmitter ilgen )
{
2009-02-23 08:17:21 +03:00
ilgen . Emit ( OpCodes . Call , getTypeHandle ) ;
2009-02-22 11:19:30 +03:00
LocalBuilder local = ilgen . DeclareLocal ( typeof ( RuntimeTypeHandle ) ) ;
ilgen . Emit ( OpCodes . Stloc , local ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
2009-02-23 08:17:21 +03:00
ilgen . Emit ( OpCodes . Call , get_Value ) ;
2009-02-22 11:19:30 +03:00
}
2005-02-11 17:46:58 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2008-06-03 11:13:49 +04:00
static class AttributeHelper
2005-02-16 14:20:43 +03:00
{
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder hideFromJavaAttribute ;
2006-04-11 18:59:43 +04:00
#if STATIC_COMPILER
2006-05-04 12:09:56 +04:00
private static CustomAttributeBuilder ghostInterfaceAttribute ;
private static CustomAttributeBuilder deprecatedAttribute ;
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder editorBrowsableNever ;
private static ConstructorInfo implementsAttribute ;
private static ConstructorInfo throwsAttribute ;
private static ConstructorInfo sourceFileAttribute ;
2005-08-22 16:42:02 +04:00
private static ConstructorInfo lineNumberTableAttribute1 ;
private static ConstructorInfo lineNumberTableAttribute2 ;
2005-10-01 15:16:11 +04:00
private static ConstructorInfo enclosingMethodAttribute ;
private static ConstructorInfo signatureAttribute ;
private static CustomAttributeBuilder paramArrayAttribute ;
2007-10-10 09:31:57 +04:00
private static ConstructorInfo nonNestedInnerClassAttribute ;
private static ConstructorInfo nonNestedOuterClassAttribute ;
2008-05-20 11:43:42 +04:00
private static Type typeofModifiers = JVM . LoadType ( typeof ( Modifiers ) ) ;
private static Type typeofSourceFileAttribute = JVM . LoadType ( typeof ( SourceFileAttribute ) ) ;
private static Type typeofLineNumberTableAttribute = JVM . LoadType ( typeof ( LineNumberTableAttribute ) ) ;
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
#endif // !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
private static Type typeofRemappedClassAttribute = JVM . LoadType ( typeof ( RemappedClassAttribute ) ) ;
private static Type typeofRemappedTypeAttribute = JVM . LoadType ( typeof ( RemappedTypeAttribute ) ) ;
private static Type typeofModifiersAttribute = JVM . LoadType ( typeof ( ModifiersAttribute ) ) ;
private static Type typeofRemappedInterfaceMethodAttribute = JVM . LoadType ( typeof ( RemappedInterfaceMethodAttribute ) ) ;
private static Type typeofNameSigAttribute = JVM . LoadType ( typeof ( NameSigAttribute ) ) ;
private static Type typeofJavaModuleAttribute = JVM . LoadType ( typeof ( JavaModuleAttribute ) ) ;
private static Type typeofSignatureAttribute = JVM . LoadType ( typeof ( SignatureAttribute ) ) ;
private static Type typeofInnerClassAttribute = JVM . LoadType ( typeof ( InnerClassAttribute ) ) ;
private static Type typeofImplementsAttribute = JVM . LoadType ( typeof ( ImplementsAttribute ) ) ;
private static Type typeofGhostInterfaceAttribute = JVM . LoadType ( typeof ( GhostInterfaceAttribute ) ) ;
private static Type typeofExceptionIsUnsafeForMappingAttribute = JVM . LoadType ( typeof ( ExceptionIsUnsafeForMappingAttribute ) ) ;
private static Type typeofThrowsAttribute = JVM . LoadType ( typeof ( ThrowsAttribute ) ) ;
private static Type typeofHideFromReflectionAttribute = JVM . LoadType ( typeof ( HideFromReflectionAttribute ) ) ;
private static Type typeofHideFromJavaAttribute = JVM . LoadType ( typeof ( HideFromJavaAttribute ) ) ;
private static Type typeofNoPackagePrefixAttribute = JVM . LoadType ( typeof ( NoPackagePrefixAttribute ) ) ;
private static Type typeofConstantValueAttribute = JVM . LoadType ( typeof ( ConstantValueAttribute ) ) ;
2007-03-13 10:44:23 +03:00
private static Type typeofAnnotationAttributeAttribute = JVM . LoadType ( typeof ( AnnotationAttributeAttribute ) ) ;
2007-10-10 09:31:57 +04:00
private static Type typeofNonNestedInnerClassAttribute = JVM . LoadType ( typeof ( NonNestedInnerClassAttribute ) ) ;
private static Type typeofNonNestedOuterClassAttribute = JVM . LoadType ( typeof ( NonNestedOuterClassAttribute ) ) ;
2009-02-04 09:51:40 +03:00
private static Type typeofEnclosingMethodAttribute = JVM . LoadType ( typeof ( EnclosingMethodAttribute ) ) ;
2005-12-07 12:06:32 +03:00
2006-10-01 12:09:25 +04:00
#if STATIC_COMPILER & & ! COMPACT_FRAMEWORK
2008-08-14 09:42:43 +04:00
private static object ParseValue ( ClassLoaderWrapper loader , TypeWrapper tw , string val )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( tw = = CoreClasses . java . lang . String . Wrapper )
{
return val ;
}
else if ( tw . TypeAsTBD . IsEnum )
{
2005-12-07 12:06:32 +03:00
if ( tw . TypeAsTBD . Assembly . ReflectionOnly )
{
// TODO implement full parsing semantics
FieldInfo field = tw . TypeAsTBD . GetField ( val ) ;
if ( field = = null )
{
throw new NotImplementedException ( "Parsing enum value: " + val ) ;
}
return field . GetRawConstantValue ( ) ;
}
2005-06-01 13:49:30 +04:00
return Enum . Parse ( tw . TypeAsTBD , val ) ;
}
else if ( tw . TypeAsTBD = = typeof ( Type ) )
{
2008-08-14 09:42:43 +04:00
TypeWrapper valtw = loader . LoadClassByDottedNameFast ( val ) ;
2006-10-01 12:09:25 +04:00
if ( valtw ! = null )
{
return valtw . TypeAsBaseType ;
}
2005-06-01 13:49:30 +04:00
return Type . GetType ( val , true ) ;
}
else if ( tw = = PrimitiveTypeWrapper . BOOLEAN )
{
return bool . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . BYTE )
{
return ( byte ) sbyte . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . CHAR )
{
return char . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . SHORT )
{
return short . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . INT )
{
return int . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . FLOAT )
{
return float . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . LONG )
{
return long . Parse ( val ) ;
}
else if ( tw = = PrimitiveTypeWrapper . DOUBLE )
{
return double . Parse ( val ) ;
}
else
{
throw new NotImplementedException ( ) ;
}
2005-04-27 10:10:01 +04:00
}
2006-10-01 12:09:25 +04:00
2008-08-14 09:42:43 +04:00
private static void SetPropertiesAndFields ( ClassLoaderWrapper loader , Attribute attrib , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
Type t = attrib . GetType ( ) ;
if ( attr . Properties ! = null )
{
foreach ( IKVM . Internal . MapXml . Param prop in attr . Properties )
{
PropertyInfo pi = t . GetProperty ( prop . Name ) ;
2008-08-15 10:27:12 +04:00
pi . SetValue ( attrib , ParseValue ( loader , ClassFile . FieldTypeWrapperFromSig ( loader , prop . Sig ) , prop . Value ) , null ) ;
2005-06-01 13:49:30 +04:00
}
}
if ( attr . Fields ! = null )
{
foreach ( IKVM . Internal . MapXml . Param field in attr . Fields )
{
FieldInfo fi = t . GetField ( field . Name ) ;
2008-08-15 10:27:12 +04:00
fi . SetValue ( attrib , ParseValue ( loader , ClassFile . FieldTypeWrapperFromSig ( loader , field . Sig ) , field . Value ) ) ;
2005-06-01 13:49:30 +04:00
}
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
internal static Attribute InstantiatePseudoCustomAttribute ( ClassLoaderWrapper loader , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
Type [ ] argTypes ;
object [ ] args ;
2008-08-14 09:42:43 +04:00
GetAttributeArgsAndTypes ( loader , attr , out argTypes , out args ) ;
2005-06-01 13:49:30 +04:00
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
Attribute attrib = ci . Invoke ( args ) as Attribute ;
2008-08-14 09:42:43 +04:00
SetPropertiesAndFields ( loader , attrib , attr ) ;
2005-06-01 13:49:30 +04:00
return attrib ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
private static bool IsCodeAccessSecurityAttribute ( ClassLoaderWrapper loader , IKVM . Internal . MapXml . Attribute attr , out SecurityAction action , out PermissionSet pset )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
action = SecurityAction . Deny ;
pset = null ;
if ( attr . Type ! = null )
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
if ( typeof ( CodeAccessSecurityAttribute ) . IsAssignableFrom ( t ) )
{
Type [ ] argTypes ;
object [ ] args ;
2008-08-14 09:42:43 +04:00
GetAttributeArgsAndTypes ( loader , attr , out argTypes , out args ) ;
2005-06-01 13:49:30 +04:00
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
CodeAccessSecurityAttribute attrib = ci . Invoke ( args ) as CodeAccessSecurityAttribute ;
2008-08-14 09:42:43 +04:00
SetPropertiesAndFields ( loader , attrib , attr ) ;
2005-06-01 13:49:30 +04:00
action = attrib . Action ;
pset = new PermissionSet ( PermissionState . None ) ;
pset . AddPermission ( attrib . CreatePermission ( ) ) ;
return true ;
}
}
return false ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , TypeBuilder tb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
2008-08-14 09:42:43 +04:00
if ( IsCodeAccessSecurityAttribute ( loader , attr , out action , out pset ) )
2005-06-01 13:49:30 +04:00
{
tb . AddDeclarativeSecurity ( action , pset ) ;
}
else
{
2008-08-14 09:42:43 +04:00
tb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-06-01 13:49:30 +04:00
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , FieldBuilder fb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2008-08-14 09:42:43 +04:00
fb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , ParameterBuilder pb , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2008-08-14 09:42:43 +04:00
pb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , MethodBuilder mb , IKVM . Internal . MapXml . Attribute attr )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
2008-08-14 09:42:43 +04:00
if ( IsCodeAccessSecurityAttribute ( loader , attr , out action , out pset ) )
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
mb . AddDeclarativeSecurity ( action , pset ) ;
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-05-27 16:44:06 +04:00
{
2008-08-14 09:42:43 +04:00
mb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-05-27 16:44:06 +04:00
}
}
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , ConstructorBuilder cb , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action ;
PermissionSet pset ;
2008-08-14 09:42:43 +04:00
if ( IsCodeAccessSecurityAttribute ( loader , attr , out action , out pset ) )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
cb . AddDeclarativeSecurity ( action , pset ) ;
}
else
{
2008-08-14 09:42:43 +04:00
cb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-05-23 12:24:07 +04:00
}
}
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , PropertyBuilder pb , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2008-08-14 09:42:43 +04:00
pb . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-05-23 12:24:07 +04:00
}
2008-08-14 09:42:43 +04:00
internal static void SetCustomAttribute ( ClassLoaderWrapper loader , AssemblyBuilder ab , IKVM . Internal . MapXml . Attribute attr )
2005-05-23 12:24:07 +04:00
{
2008-08-14 09:42:43 +04:00
ab . SetCustomAttribute ( CreateCustomAttribute ( loader , attr ) ) ;
2005-05-23 12:24:07 +04:00
}
2008-08-14 09:42:43 +04:00
private static void GetAttributeArgsAndTypes ( ClassLoaderWrapper loader , IKVM . Internal . MapXml . Attribute attr , out Type [ ] argTypes , out object [ ] args )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
2008-08-15 10:27:12 +04:00
TypeWrapper [ ] twargs = ClassFile . ArgTypeWrapperListFromSig ( loader , attr . Sig ) ;
2005-06-01 13:49:30 +04:00
argTypes = new Type [ twargs . Length ] ;
args = new object [ argTypes . Length ] ;
for ( int i = 0 ; i < twargs . Length ; i + + )
{
argTypes [ i ] = twargs [ i ] . TypeAsSignatureType ;
TypeWrapper tw = twargs [ i ] ;
if ( tw = = CoreClasses . java . lang . Object . Wrapper )
{
2008-08-15 10:27:12 +04:00
tw = ClassFile . FieldTypeWrapperFromSig ( loader , attr . Params [ i ] . Sig ) ;
2005-06-01 13:49:30 +04:00
}
if ( tw . IsArray )
{
Array arr = Array . CreateInstance ( tw . ElementTypeWrapper . TypeAsArrayType , attr . Params [ i ] . Elements . Length ) ;
for ( int j = 0 ; j < arr . Length ; j + + )
{
2008-08-14 09:42:43 +04:00
arr . SetValue ( ParseValue ( loader , tw . ElementTypeWrapper , attr . Params [ i ] . Elements [ j ] . Value ) , j ) ;
2005-06-01 13:49:30 +04:00
}
args [ i ] = arr ;
}
else
{
2008-08-14 09:42:43 +04:00
args [ i ] = ParseValue ( loader , tw , attr . Params [ i ] . Value ) ;
2005-06-01 13:49:30 +04:00
}
}
2005-05-23 12:24:07 +04:00
}
2008-08-14 09:42:43 +04:00
private static CustomAttributeBuilder CreateCustomAttribute ( ClassLoaderWrapper loader , IKVM . Internal . MapXml . Attribute attr )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
Type [ ] argTypes ;
object [ ] args ;
2008-08-14 09:42:43 +04:00
GetAttributeArgsAndTypes ( loader , attr , out argTypes , out args ) ;
2005-06-01 13:49:30 +04:00
if ( attr . Type ! = null )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler . GetType ( attr . Type ) ;
2005-06-01 13:49:30 +04:00
if ( typeof ( CodeAccessSecurityAttribute ) . IsAssignableFrom ( t ) )
{
throw new NotImplementedException ( "CodeAccessSecurityAttribute support not implemented" ) ;
}
ConstructorInfo ci = t . GetConstructor ( argTypes ) ;
2005-12-07 12:06:32 +03:00
if ( ci = = null )
{
throw new InvalidOperationException ( string . Format ( "Constructor missing: {0}::<init>{1}" , attr . Class , attr . Sig ) ) ;
}
2005-06-01 13:49:30 +04:00
PropertyInfo [ ] namedProperties ;
object [ ] propertyValues ;
if ( attr . Properties ! = null )
{
namedProperties = new PropertyInfo [ attr . Properties . Length ] ;
propertyValues = new object [ attr . Properties . Length ] ;
for ( int i = 0 ; i < namedProperties . Length ; i + + )
{
namedProperties [ i ] = t . GetProperty ( attr . Properties [ i ] . Name ) ;
2008-08-15 10:27:12 +04:00
propertyValues [ i ] = ParseValue ( loader , ClassFile . FieldTypeWrapperFromSig ( loader , attr . Properties [ i ] . Sig ) , attr . Properties [ i ] . Value ) ;
2005-06-01 13:49:30 +04:00
}
}
else
{
namedProperties = new PropertyInfo [ 0 ] ;
propertyValues = new object [ 0 ] ;
}
FieldInfo [ ] namedFields ;
object [ ] fieldValues ;
if ( attr . Fields ! = null )
{
namedFields = new FieldInfo [ attr . Fields . Length ] ;
fieldValues = new object [ attr . Fields . Length ] ;
for ( int i = 0 ; i < namedFields . Length ; i + + )
{
namedFields [ i ] = t . GetField ( attr . Fields [ i ] . Name ) ;
2008-08-15 10:27:12 +04:00
fieldValues [ i ] = ParseValue ( loader , ClassFile . FieldTypeWrapperFromSig ( loader , attr . Fields [ i ] . Sig ) , attr . Fields [ i ] . Value ) ;
2005-06-01 13:49:30 +04:00
}
}
else
{
namedFields = new FieldInfo [ 0 ] ;
fieldValues = new object [ 0 ] ;
}
return new CustomAttributeBuilder ( ci , args , namedProperties , propertyValues , namedFields , fieldValues ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( attr . Properties ! = null )
{
throw new NotImplementedException ( "Setting property values on Java attributes is not implemented" ) ;
}
2008-08-14 09:42:43 +04:00
TypeWrapper t = loader . LoadClassByDottedName ( attr . Class ) ;
2005-06-01 13:49:30 +04:00
MethodWrapper mw = t . GetMethodWrapper ( "<init>" , attr . Sig , false ) ;
mw . Link ( ) ;
ConstructorInfo ci = ( ConstructorInfo ) mw . GetMethod ( ) ;
2005-12-07 12:06:32 +03:00
if ( ci = = null )
{
throw new InvalidOperationException ( string . Format ( "Constructor missing: {0}::<init>{1}" , attr . Class , attr . Sig ) ) ;
}
2005-06-01 13:49:30 +04:00
FieldInfo [ ] namedFields ;
object [ ] fieldValues ;
if ( attr . Fields ! = null )
{
namedFields = new FieldInfo [ attr . Fields . Length ] ;
fieldValues = new object [ attr . Fields . Length ] ;
for ( int i = 0 ; i < namedFields . Length ; i + + )
{
FieldWrapper fw = t . GetFieldWrapper ( attr . Fields [ i ] . Name , attr . Fields [ i ] . Sig ) ;
fw . Link ( ) ;
namedFields [ i ] = fw . GetField ( ) ;
2008-08-15 10:27:12 +04:00
fieldValues [ i ] = ParseValue ( loader , ClassFile . FieldTypeWrapperFromSig ( loader , attr . Fields [ i ] . Sig ) , attr . Fields [ i ] . Value ) ;
2005-06-01 13:49:30 +04:00
}
}
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
namedFields = new FieldInfo [ 0 ] ;
fieldValues = new object [ 0 ] ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
return new CustomAttributeBuilder ( ci , args , namedFields , fieldValues ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
#endif
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2007-09-11 16:12:35 +04:00
internal static void SetEditorBrowsableNever ( TypeBuilder tb )
{
if ( editorBrowsableNever = = null )
{
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
}
tb . SetCustomAttribute ( editorBrowsableNever ) ;
}
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever ( MethodBuilder mb )
{
if ( editorBrowsableNever = = null )
2005-04-27 10:10:01 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( editorBrowsableNever ) ;
2005-04-27 10:10:01 +04:00
}
2005-05-23 12:24:07 +04:00
2006-12-28 10:46:21 +03:00
internal static void SetEditorBrowsableNever ( ConstructorBuilder cb )
{
if ( editorBrowsableNever = = null )
{
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
}
cb . SetCustomAttribute ( editorBrowsableNever ) ;
}
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever ( PropertyBuilder pb )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( editorBrowsableNever = = null )
2005-05-23 12:24:07 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder ( StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableAttribute" ) . GetConstructor ( new Type [ ] { StaticCompiler . GetType ( "System.ComponentModel.EditorBrowsableState" ) } ) , new object [ ] { ( int ) System . ComponentModel . EditorBrowsableState . Never } ) ;
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
pb . SetCustomAttribute ( editorBrowsableNever ) ;
}
internal static void SetDeprecatedAttribute ( MethodBase mb )
{
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder ;
if ( method ! = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
method . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
internal static void SetDeprecatedAttribute ( TypeBuilder tb )
{
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
tb . SetCustomAttribute ( deprecatedAttribute ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetDeprecatedAttribute ( FieldBuilder fb )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( deprecatedAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( deprecatedAttribute ) ;
}
2006-10-04 13:03:18 +04:00
internal static void SetDeprecatedAttribute ( PropertyBuilder pb )
{
if ( deprecatedAttribute = = null )
{
deprecatedAttribute = new CustomAttributeBuilder ( typeof ( ObsoleteAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
}
pb . SetCustomAttribute ( deprecatedAttribute ) ;
}
2005-06-01 13:49:30 +04:00
internal static void SetThrowsAttribute ( MethodBase mb , string [ ] exceptions )
{
if ( exceptions ! = null & & exceptions . Length ! = 0 )
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if ( throwsAttribute = = null )
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
throwsAttribute = typeofThrowsAttribute . GetConstructor ( new Type [ ] { typeof ( string [ ] ) } ) ;
2005-06-01 13:49:30 +04:00
}
if ( mb is MethodBuilder )
{
MethodBuilder method = ( MethodBuilder ) mb ;
method . SetCustomAttribute ( new CustomAttributeBuilder ( throwsAttribute , new object [ ] { exceptions } ) ) ;
}
else
{
ConstructorBuilder constructor = ( ConstructorBuilder ) mb ;
constructor . SetCustomAttribute ( new CustomAttributeBuilder ( throwsAttribute , new object [ ] { exceptions } ) ) ;
2005-04-27 10:10:01 +04:00
}
}
2004-11-23 20:46:39 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void SetGhostInterface ( TypeBuilder typeBuilder )
2004-11-23 20:46:39 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ghostInterfaceAttribute = = null )
{
2005-12-07 12:06:32 +03:00
ghostInterfaceAttribute = new CustomAttributeBuilder ( typeofGhostInterfaceAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( ghostInterfaceAttribute ) ;
2004-11-23 20:46:39 +03:00
}
2007-10-10 09:31:57 +04:00
internal static void SetNonNestedInnerClass ( TypeBuilder typeBuilder , string className )
{
if ( nonNestedInnerClassAttribute = = null )
{
nonNestedInnerClassAttribute = typeofNonNestedInnerClassAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
}
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( nonNestedInnerClassAttribute , new object [ ] { className } ) ) ;
}
internal static void SetNonNestedOuterClass ( TypeBuilder typeBuilder , string className )
{
if ( nonNestedOuterClassAttribute = = null )
{
nonNestedOuterClassAttribute = typeofNonNestedOuterClassAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
}
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( nonNestedOuterClassAttribute , new object [ ] { className } ) ) ;
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection ( MethodBuilder mb )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( cab ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection ( FieldBuilder fb )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-08-14 19:49:50 +04:00
fb . SetCustomAttribute ( cab ) ;
}
internal static void HideFromReflection ( PropertyBuilder pb )
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofHideFromReflectionAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-08-14 19:49:50 +04:00
pb . SetCustomAttribute ( cab ) ;
}
2006-04-10 13:09:09 +04:00
#endif // !COMPACT_FRAMEWORK
2005-08-14 19:49:50 +04:00
internal static bool IsHideFromReflection ( MethodInfo mi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( mi , typeofHideFromReflectionAttribute ) ;
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection ( FieldInfo fi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( fi , typeofHideFromReflectionAttribute ) ;
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection ( PropertyInfo pi )
{
2005-12-07 12:06:32 +03:00
return IsDefined ( pi , typeofHideFromReflectionAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( TypeBuilder typeBuilder )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( ConstructorBuilder cb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
cb . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( MethodBuilder mb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2005-06-01 13:49:30 +04:00
}
mb . SetCustomAttribute ( hideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava ( FieldBuilder fb )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if ( hideFromJavaAttribute = = null )
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( hideFromJavaAttribute ) ;
}
2006-09-26 08:53:16 +04:00
#if STATIC_COMPILER
internal static void HideFromJava ( PropertyBuilder pb )
{
if ( hideFromJavaAttribute = = null )
{
hideFromJavaAttribute = new CustomAttributeBuilder ( typeofHideFromJavaAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
}
pb . SetCustomAttribute ( hideFromJavaAttribute ) ;
}
#endif // STATIC_COMPILER
#endif // !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static bool IsHideFromJava ( Type type )
{
return IsDefined ( type , typeofHideFromJavaAttribute ) ;
}
2005-06-01 13:49:30 +04:00
internal static bool IsHideFromJava ( MemberInfo mi )
{
// NOTE all privatescope fields and methods are "hideFromJava"
// because Java cannot deal with the potential name clashes
FieldInfo fi = mi as FieldInfo ;
if ( fi ! = null & & ( fi . Attributes & FieldAttributes . FieldAccessMask ) = = FieldAttributes . PrivateScope )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
MethodBase mb = mi as MethodBase ;
if ( mb ! = null & & ( mb . Attributes & MethodAttributes . MemberAccessMask ) = = MethodAttributes . PrivateScope )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
2003-11-17 15:01:50 +03:00
}
2005-12-07 12:06:32 +03:00
return IsDefined ( mi , typeofHideFromJavaAttribute ) ;
2003-11-17 15:01:50 +03:00
}
2003-10-17 12:08:31 +04:00
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER & & ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void SetImplementsAttribute ( TypeBuilder typeBuilder , TypeWrapper [ ] ifaceWrappers )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ifaceWrappers ! = null & & ifaceWrappers . Length ! = 0 )
{
string [ ] interfaces = new string [ ifaceWrappers . Length ] ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
{
interfaces [ i ] = ifaceWrappers [ i ] . Name ;
}
if ( implementsAttribute = = null )
{
2005-12-07 12:06:32 +03:00
implementsAttribute = typeofImplementsAttribute . GetConstructor ( new Type [ ] { typeof ( string [ ] ) } ) ;
2005-06-01 13:49:30 +04:00
}
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( implementsAttribute , new object [ ] { interfaces } ) ) ;
}
}
2005-12-07 12:06:32 +03:00
#endif
internal static bool IsGhostInterface ( Type type )
{
return IsDefined ( type , typeofGhostInterfaceAttribute ) ;
}
internal static bool IsRemappedType ( Type type )
{
return IsDefined ( type , typeofRemappedTypeAttribute ) ;
}
internal static bool IsExceptionIsUnsafeForMapping ( Type type )
{
return IsDefined ( type , typeofExceptionIsUnsafeForMappingAttribute ) ;
}
2007-11-26 11:38:38 +03:00
#if ! COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
// this method compares t1 and t2 by name
// if the type name and assembly name (ignoring the version and strong name) match
// the type are considered the same
private static bool MatchTypes ( Type t1 , Type t2 )
{
return t1 . FullName = = t2 . FullName
& & t1 . Assembly . GetName ( ) . Name = = t2 . Assembly . GetName ( ) . Name ;
}
#endif
2007-03-13 10:44:23 +03:00
internal static object GetConstantValue ( FieldInfo field )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! field . DeclaringType . Assembly . ReflectionOnly )
{
// In Java, instance fields can also have a ConstantValue attribute so we emulate that
// with ConstantValueAttribute (for consumption by ikvmstub only)
object [ ] attrib = field . GetCustomAttributes ( typeof ( ConstantValueAttribute ) , false ) ;
if ( attrib . Length = = 1 )
{
return ( ( ConstantValueAttribute ) attrib [ 0 ] ) . GetConstantValue ( ) ;
}
return null ;
}
else
#endif
2007-03-13 10:44:23 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2007-03-13 10:44:23 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( field ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofConstantValueAttribute ) )
{
return cad . ConstructorArguments [ 0 ] . Value ;
}
}
#endif
2008-03-14 12:12:50 +03:00
return null ;
2007-03-13 10:44:23 +03:00
}
}
2005-12-07 12:06:32 +03:00
internal static ModifiersAttribute GetModifiersAttribute ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
object [ ] attr = type . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
return attr . Length = = 1 ? ( ModifiersAttribute ) attr [ 0 ] : null ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofModifiersAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
2005-12-07 12:06:32 +03:00
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
2004-08-17 13:05:21 +04:00
2008-04-14 09:13:41 +04:00
internal static ModifiersAttribute GetModifiersAttribute ( PropertyInfo property )
{
#if ! STATIC_COMPILER
if ( ! property . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] attr = property . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
return attr . Length = = 1 ? ( ModifiersAttribute ) attr [ 0 ] : null ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( property ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofModifiersAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
if ( args . Count = = 2 )
{
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
return new ModifiersAttribute ( ( Modifiers ) args [ 0 ] . Value ) ;
}
}
#endif
return null ;
}
}
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers ( MethodBase mb , bool assemblyIsPrivate )
2003-10-17 12:08:31 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! mb . DeclaringType . Assembly . ReflectionOnly )
2005-06-01 13:49:30 +04:00
{
2008-03-14 12:12:50 +03:00
object [ ] customAttribute = mb . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
if ( customAttribute . Length = = 1 )
{
ModifiersAttribute mod = ( ModifiersAttribute ) customAttribute [ 0 ] ;
return new ExModifiers ( mod . Modifiers , mod . IsInternal ) ;
}
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mb ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofModifiersAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , false ) ;
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0 ;
if ( mb . IsPublic )
{
modifiers | = Modifiers . Public ;
}
else if ( mb . IsPrivate )
{
modifiers | = Modifiers . Private ;
}
else if ( mb . IsFamily | | mb . IsFamilyOrAssembly )
{
modifiers | = Modifiers . Protected ;
}
else if ( assemblyIsPrivate )
{
modifiers | = Modifiers . Private ;
}
// NOTE Java doesn't support non-virtual methods, but we set the Final modifier for
// non-virtual methods to approximate the semantics
if ( ( mb . IsFinal | | ( ! mb . IsVirtual & & ( ( modifiers & Modifiers . Private ) = = 0 ) ) ) & & ! mb . IsStatic & & ! mb . IsConstructor )
{
modifiers | = Modifiers . Final ;
}
if ( mb . IsAbstract )
{
modifiers | = Modifiers . Abstract ;
}
else
{
// Some .NET interfaces (like System._AppDomain) have synchronized methods,
// Java doesn't allow synchronized on an abstract methods, so we ignore it for
// abstract methods.
if ( ( mb . GetMethodImplementationFlags ( ) & MethodImplAttributes . Synchronized ) ! = 0 )
{
modifiers | = Modifiers . Synchronized ;
}
}
if ( mb . IsStatic )
{
modifiers | = Modifiers . Static ;
}
if ( ( mb . Attributes & MethodAttributes . PinvokeImpl ) ! = 0 )
{
modifiers | = Modifiers . Native ;
}
2005-10-01 15:16:11 +04:00
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
2005-12-07 12:06:32 +03:00
if ( parameters . Length > 0 & & IsDefined ( parameters [ parameters . Length - 1 ] , typeof ( ParamArrayAttribute ) ) )
2005-10-01 15:16:11 +04:00
{
modifiers | = Modifiers . VarArgs ;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2003-10-17 12:08:31 +04:00
}
2003-05-30 16:08:59 +04:00
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers ( FieldInfo fi , bool assemblyIsPrivate )
2003-05-30 16:08:59 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! fi . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] customAttribute = fi . GetCustomAttributes ( typeof ( ModifiersAttribute ) , false ) ;
if ( customAttribute . Length = = 1 )
{
ModifiersAttribute mod = ( ModifiersAttribute ) customAttribute [ 0 ] ;
return new ExModifiers ( mod . Modifiers , mod . IsInternal ) ;
}
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( fi ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofModifiersAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
2006-04-05 12:18:58 +04:00
if ( args . Count = = 2 )
{
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , ( bool ) args [ 1 ] . Value ) ;
}
return new ExModifiers ( ( Modifiers ) args [ 0 ] . Value , false ) ;
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0 ;
if ( fi . IsPublic )
{
modifiers | = Modifiers . Public ;
}
else if ( fi . IsPrivate )
{
modifiers | = Modifiers . Private ;
}
else if ( fi . IsFamily | | fi . IsFamilyOrAssembly )
{
modifiers | = Modifiers . Protected ;
}
else if ( assemblyIsPrivate )
{
modifiers | = Modifiers . Private ;
}
if ( fi . IsInitOnly | | fi . IsLiteral )
{
modifiers | = Modifiers . Final ;
}
if ( fi . IsNotSerialized )
{
modifiers | = Modifiers . Transient ;
}
if ( fi . IsStatic )
{
modifiers | = Modifiers . Static ;
}
2006-10-04 16:51:19 +04:00
if ( Array . IndexOf ( fi . GetRequiredCustomModifiers ( ) , typeof ( System . Runtime . CompilerServices . IsVolatile ) ) ! = - 1 )
{
modifiers | = Modifiers . Volatile ;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2003-05-30 16:08:59 +04:00
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER & & ! COMPACT_FRAMEWORK
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( MethodBuilder mb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
mb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( ConstructorBuilder cb , Modifiers modifiers , bool isInternal )
2003-10-17 12:08:31 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
cb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( FieldBuilder fb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2008-04-14 09:13:41 +04:00
internal static void SetModifiers ( PropertyBuilder pb , Modifiers modifiers , bool isInternal )
{
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
pb . SetCustomAttribute ( customAttributeBuilder ) ;
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers ( TypeBuilder tb , Modifiers modifiers , bool isInternal )
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder ;
if ( isInternal )
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers , typeof ( bool ) } ) , new object [ ] { modifiers , isInternal } ) ;
}
else
{
customAttributeBuilder = new CustomAttributeBuilder ( typeofModifiersAttribute . GetConstructor ( new Type [ ] { typeofModifiers } ) , new object [ ] { modifiers } ) ;
}
2005-06-01 13:49:30 +04:00
tb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetNameSig ( MethodBase mb , string name , string sig )
2003-07-24 11:29:51 +04:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( typeofNameSigAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , sig } ) ;
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder ;
if ( method ! = null )
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
method . SetCustomAttribute ( customAttributeBuilder ) ;
2004-05-14 13:31:54 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( customAttributeBuilder ) ;
2004-05-14 13:31:54 +04:00
}
2003-08-05 18:07:22 +04:00
}
2003-07-24 11:29:51 +04:00
2005-06-01 13:49:30 +04:00
internal static void SetNameSig ( FieldBuilder fb , string name , string sig )
2003-12-24 14:51:41 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( typeofNameSigAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , sig } ) ;
2005-06-01 13:49:30 +04:00
fb . SetCustomAttribute ( customAttributeBuilder ) ;
2003-12-24 14:51:41 +03:00
}
2005-06-01 13:49:30 +04:00
internal static byte [ ] FreezeDryType ( Type type )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
System . IO . MemoryStream mem = new System . IO . MemoryStream ( ) ;
System . IO . BinaryWriter bw = new System . IO . BinaryWriter ( mem , System . Text . UTF8Encoding . UTF8 ) ;
bw . Write ( ( short ) 1 ) ;
bw . Write ( type . FullName ) ;
bw . Write ( ( short ) 0 ) ;
return mem . ToArray ( ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2005-07-07 15:24:08 +04:00
internal static void SetInnerClass ( TypeBuilder typeBuilder , string innerClass , Modifiers modifiers )
2003-05-30 16:08:59 +04:00
{
2005-12-07 12:06:32 +03:00
Type [ ] argTypes = new Type [ ] { typeof ( string ) , typeofModifiers } ;
2005-07-07 15:24:08 +04:00
object [ ] args = new object [ ] { innerClass , modifiers } ;
2005-12-07 12:06:32 +03:00
ConstructorInfo ci = typeofInnerClassAttribute . GetConstructor ( argTypes ) ;
2005-06-01 13:49:30 +04:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder ( ci , args ) ;
typeBuilder . SetCustomAttribute ( customAttributeBuilder ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetSourceFile ( TypeBuilder typeBuilder , string filename )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if ( sourceFileAttribute = = null )
2003-08-21 14:06:34 +04:00
{
2005-12-07 12:06:32 +03:00
sourceFileAttribute = typeofSourceFileAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( sourceFileAttribute , new object [ ] { filename } ) ) ;
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
internal static void SetSourceFile ( ModuleBuilder moduleBuilder , string filename )
{
if ( sourceFileAttribute = = null )
{
sourceFileAttribute = typeofSourceFileAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
}
moduleBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( sourceFileAttribute , new object [ ] { filename } ) ) ;
}
2005-08-22 16:42:02 +04:00
internal static void SetLineNumberTable ( MethodBase mb , IKVM . Attributes . LineNumberTableAttribute . LineNumberWriter writer )
2003-05-30 16:08:59 +04:00
{
2005-08-22 16:42:02 +04:00
object arg ;
ConstructorInfo con ;
if ( writer . Count = = 1 )
2005-06-01 13:49:30 +04:00
{
2005-08-22 16:42:02 +04:00
if ( lineNumberTableAttribute2 = = null )
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute2 = typeofLineNumberTableAttribute . GetConstructor ( new Type [ ] { typeof ( ushort ) } ) ;
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute2 ;
arg = ( ushort ) writer . LineNo ;
}
else
{
if ( lineNumberTableAttribute1 = = null )
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute1 = typeofLineNumberTableAttribute . GetConstructor ( new Type [ ] { typeof ( byte [ ] ) } ) ;
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute1 ;
arg = writer . ToArray ( ) ;
2005-06-01 13:49:30 +04:00
}
if ( mb is ConstructorBuilder )
{
2005-08-22 16:42:02 +04:00
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( con , new object [ ] { arg } ) ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2005-08-22 16:42:02 +04:00
( ( MethodBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( con , new object [ ] { arg } ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-05-30 16:08:59 +04:00
}
2005-10-01 15:16:11 +04:00
internal static void SetEnclosingMethodAttribute ( TypeBuilder tb , string className , string methodName , string methodSig )
{
if ( enclosingMethodAttribute = = null )
{
2005-12-07 12:06:32 +03:00
enclosingMethodAttribute = typeofEnclosingMethodAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) , typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
tb . SetCustomAttribute ( new CustomAttributeBuilder ( enclosingMethodAttribute , new object [ ] { className , methodName , methodSig } ) ) ;
}
internal static void SetSignatureAttribute ( TypeBuilder tb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
tb . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
internal static void SetSignatureAttribute ( FieldBuilder fb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
fb . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
internal static void SetSignatureAttribute ( MethodBase mb , string signature )
{
if ( signatureAttribute = = null )
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute . GetConstructor ( new Type [ ] { typeof ( string ) } ) ;
2005-10-01 15:16:11 +04:00
}
if ( mb is ConstructorBuilder )
{
( ( ConstructorBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
else
{
( ( MethodBuilder ) mb ) . SetCustomAttribute ( new CustomAttributeBuilder ( signatureAttribute , new object [ ] { signature } ) ) ;
}
}
internal static void SetParamArrayAttribute ( ParameterBuilder pb )
{
if ( paramArrayAttribute = = null )
{
paramArrayAttribute = new CustomAttributeBuilder ( typeof ( ParamArrayAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
}
pb . SetCustomAttribute ( paramArrayAttribute ) ;
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER && !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static NameSigAttribute GetNameSig ( FieldInfo field )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! field . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] attr = field . GetCustomAttributes ( typeof ( NameSigAttribute ) , false ) ;
return attr . Length = = 1 ? ( NameSigAttribute ) attr [ 0 ] : null ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( field ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofNameSigAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new NameSigAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
internal static NameSigAttribute GetNameSig ( MethodBase method )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! method . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] attr = method . GetCustomAttributes ( typeof ( NameSigAttribute ) , false ) ;
return attr . Length = = 1 ? ( NameSigAttribute ) attr [ 0 ] : null ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( method ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofNameSigAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new NameSigAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
2007-11-26 11:38:38 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
internal static T [ ] DecodeArray < T > ( CustomAttributeTypedArgument arg )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > elems = ( IList < CustomAttributeTypedArgument > ) arg . Value ;
T [ ] arr = new T [ elems . Count ] ;
for ( int i = 0 ; i < arr . Length ; i + + )
{
arr [ i ] = ( T ) elems [ i ] . Value ;
}
return arr ;
}
#endif
internal static ImplementsAttribute GetImplements ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
{
object [ ] attribs = type . GetCustomAttributes ( typeof ( ImplementsAttribute ) , false ) ;
return attribs . Length = = 1 ? ( ImplementsAttribute ) attribs [ 0 ] : null ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofImplementsAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new ImplementsAttribute ( DecodeArray < string > ( args [ 0 ] ) ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
2006-07-21 14:18:13 +04:00
internal static ThrowsAttribute GetThrows ( MethodBase mb )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! mb . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] attribs = mb . GetCustomAttributes ( typeof ( ThrowsAttribute ) , false ) ;
return attribs . Length = = 1 ? ( ThrowsAttribute ) attribs [ 0 ] : null ;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mb ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofThrowsAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new ThrowsAttribute ( DecodeArray < string > ( args [ 0 ] ) ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2006-07-21 14:18:13 +04:00
return null ;
}
}
2007-10-10 09:31:57 +04:00
internal static string [ ] GetNonNestedInnerClasses ( Type t )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! t . Assembly . ReflectionOnly )
{
object [ ] attribs = t . GetCustomAttributes ( typeof ( NonNestedInnerClassAttribute ) , false ) ;
string [ ] classes = new string [ attribs . Length ] ;
for ( int i = 0 ; i < attribs . Length ; i + + )
{
classes [ i ] = ( ( NonNestedInnerClassAttribute ) attribs [ i ] ) . InnerClassName ;
}
return classes ;
}
else
#endif
2007-10-10 09:31:57 +04:00
{
List < string > list = new List < string > ( ) ;
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2007-10-10 09:31:57 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( t ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofNonNestedInnerClassAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
list . Add ( ( string ) args [ 0 ] . Value ) ;
}
}
#endif
2008-03-14 12:12:50 +03:00
return list . ToArray ( ) ;
2007-10-10 09:31:57 +04:00
}
}
internal static string GetNonNestedOuterClasses ( Type t )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! t . Assembly . ReflectionOnly )
{
object [ ] attribs = t . GetCustomAttributes ( typeof ( NonNestedOuterClassAttribute ) , false ) ;
return attribs . Length = = 1 ? ( ( NonNestedOuterClassAttribute ) attribs [ 0 ] ) . OuterClassName : null ;
}
else
#endif
2007-10-10 09:31:57 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2007-10-10 09:31:57 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( t ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofNonNestedOuterClassAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return ( string ) args [ 0 ] . Value ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2007-10-10 09:31:57 +04:00
return null ;
}
}
2006-07-21 14:18:13 +04:00
internal static SignatureAttribute GetSignature ( MethodBase mb )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! mb . DeclaringType . Assembly . ReflectionOnly )
2006-07-21 14:18:13 +04:00
{
2008-03-14 12:12:50 +03:00
object [ ] attribs = mb . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
return attribs . Length = = 1 ? ( SignatureAttribute ) attribs [ 0 ] : null ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mb ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofSignatureAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new SignatureAttribute ( ( string ) args [ 0 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2006-07-21 14:18:13 +04:00
return null ;
}
}
internal static SignatureAttribute GetSignature ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
{
object [ ] attribs = type . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
return attribs . Length = = 1 ? ( SignatureAttribute ) attribs [ 0 ] : null ;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofSignatureAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new SignatureAttribute ( ( string ) args [ 0 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2006-07-21 14:18:13 +04:00
return null ;
}
}
internal static SignatureAttribute GetSignature ( FieldInfo fi )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! fi . DeclaringType . Assembly . ReflectionOnly )
{
object [ ] attribs = fi . GetCustomAttributes ( typeof ( SignatureAttribute ) , false ) ;
return attribs . Length = = 1 ? ( SignatureAttribute ) attribs [ 0 ] : null ;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( fi ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofSignatureAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new SignatureAttribute ( ( string ) args [ 0 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2006-07-21 14:18:13 +04:00
return null ;
}
}
2005-12-07 12:06:32 +03:00
internal static InnerClassAttribute GetInnerClass ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
{
object [ ] attribs = type . GetCustomAttributes ( typeof ( InnerClassAttribute ) , false ) ;
return attribs . Length = = 1 ? ( InnerClassAttribute ) attribs [ 0 ] : null ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofInnerClassAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new InnerClassAttribute ( ( string ) args [ 0 ] . Value , ( Modifiers ) args [ 1 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
internal static RemappedInterfaceMethodAttribute [ ] GetRemappedInterfaceMethods ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
{
object [ ] attr = type . GetCustomAttributes ( typeof ( RemappedInterfaceMethodAttribute ) , false ) ;
RemappedInterfaceMethodAttribute [ ] attr1 = new RemappedInterfaceMethodAttribute [ attr . Length ] ;
Array . Copy ( attr , attr1 , attr . Length ) ;
return attr1 ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
List < RemappedInterfaceMethodAttribute > attrs = new List < RemappedInterfaceMethodAttribute > ( ) ;
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofRemappedInterfaceMethodAttribute ) )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
attrs . Add ( new RemappedInterfaceMethodAttribute ( ( string ) args [ 0 ] . Value , ( string ) args [ 1 ] . Value ) ) ;
2005-12-07 12:06:32 +03:00
}
2008-03-14 12:12:50 +03:00
}
#endif
2005-12-07 12:06:32 +03:00
return attrs . ToArray ( ) ;
}
}
internal static RemappedTypeAttribute GetRemappedType ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
object [ ] attribs = type . GetCustomAttributes ( typeof ( RemappedTypeAttribute ) , false ) ;
return attribs . Length = = 1 ? ( RemappedTypeAttribute ) attribs [ 0 ] : null ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofRemappedTypeAttribute ) )
2005-12-07 12:06:32 +03:00
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
return new RemappedTypeAttribute ( ( Type ) args [ 0 ] . Value ) ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return null ;
}
}
internal static RemappedClassAttribute [ ] GetRemappedClasses ( Assembly coreAssembly )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! coreAssembly . ReflectionOnly )
{
object [ ] attr = coreAssembly . GetCustomAttributes ( typeof ( RemappedClassAttribute ) , false ) ;
RemappedClassAttribute [ ] attr1 = new RemappedClassAttribute [ attr . Length ] ;
Array . Copy ( attr , attr1 , attr . Length ) ;
return attr1 ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
List < RemappedClassAttribute > attrs = new List < RemappedClassAttribute > ( ) ;
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( coreAssembly ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofRemappedClassAttribute ) )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
attrs . Add ( new RemappedClassAttribute ( ( string ) args [ 0 ] . Value , ( Type ) args [ 1 ] . Value ) ) ;
2005-12-07 12:06:32 +03:00
}
2008-03-14 12:12:50 +03:00
}
#endif
2005-12-07 12:06:32 +03:00
return attrs . ToArray ( ) ;
}
}
2006-04-11 18:59:43 +04:00
internal static string GetAnnotationAttributeType ( Type type )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
2007-03-13 10:44:23 +03:00
{
2008-03-14 12:12:50 +03:00
object [ ] attr = type . GetCustomAttributes ( typeof ( AnnotationAttributeAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( AnnotationAttributeAttribute ) attr [ 0 ] ) . AttributeType ;
}
return null ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2007-03-13 10:44:23 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofAnnotationAttributeAttribute ) )
{
return ( string ) cad . ConstructorArguments [ 0 ] . Value ;
}
}
#endif
2008-03-14 12:12:50 +03:00
return null ;
2006-04-11 18:59:43 +04:00
}
}
2007-12-17 13:59:02 +03:00
internal static AssemblyName [ ] GetInternalsVisibleToAttributes ( Assembly assembly )
{
List < AssemblyName > list = new List < AssemblyName > ( ) ;
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( assembly ) )
{
2007-12-27 18:08:05 +03:00
if ( cad . Constructor . DeclaringType = = typeof ( System . Runtime . CompilerServices . InternalsVisibleToAttribute ) )
2007-12-17 13:59:02 +03:00
{
try
{
list . Add ( new AssemblyName ( ( string ) cad . ConstructorArguments [ 0 ] . Value ) ) ;
}
catch
{
// HACK since there is no list of exception that the AssemblyName constructor can throw, we simply catch all
}
}
}
return list . ToArray ( ) ;
}
2005-12-07 12:06:32 +03:00
internal static bool IsDefined ( Module mod , Type attribute )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! mod . Assembly . ReflectionOnly )
{
return mod . IsDefined ( attribute , false ) ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mod ) )
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , attribute ) )
2005-12-07 12:06:32 +03:00
{
return true ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return false ;
}
}
internal static bool IsDefined ( Assembly asm , Type attribute )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! asm . ReflectionOnly )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
return asm . IsDefined ( attribute , false ) ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( asm ) )
{
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , attribute ) )
2005-12-07 12:06:32 +03:00
{
return true ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return false ;
}
}
internal static bool IsDefined ( Type type , Type attribute )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! type . Assembly . ReflectionOnly )
{
return type . IsDefined ( attribute , false ) ;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , attribute ) )
2005-12-07 12:06:32 +03:00
{
return true ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return false ;
}
}
internal static bool IsDefined ( ParameterInfo pi , Type attribute )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! pi . Member . DeclaringType . Assembly . ReflectionOnly )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
return pi . IsDefined ( attribute , false ) ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( pi ) )
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , attribute ) )
2005-12-07 12:06:32 +03:00
{
return true ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return false ;
}
}
internal static bool IsDefined ( MemberInfo member , Type attribute )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! member . DeclaringType . Assembly . ReflectionOnly )
2005-12-07 12:06:32 +03:00
{
2008-03-14 12:12:50 +03:00
return member . IsDefined ( attribute , false ) ;
}
else
#endif
{
#if ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( member ) )
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if ( MatchTypes ( cad . Constructor . DeclaringType , attribute ) )
2005-12-07 12:06:32 +03:00
{
return true ;
}
}
2008-03-14 12:12:50 +03:00
#endif
2005-12-07 12:06:32 +03:00
return false ;
}
}
internal static bool IsJavaModule ( Module mod )
{
return IsDefined ( mod , typeofJavaModuleAttribute ) ;
}
2006-10-09 12:29:42 +04:00
internal static object [ ] GetJavaModuleAttributes ( Module mod )
{
2008-03-14 12:12:50 +03:00
#if ! STATIC_COMPILER
if ( ! mod . Assembly . ReflectionOnly )
{
return mod . GetCustomAttributes ( typeofJavaModuleAttribute , false ) ;
}
else
#endif
2006-10-09 16:32:33 +04:00
{
2008-08-15 16:01:06 +04:00
List < JavaModuleAttribute > attrs = new List < JavaModuleAttribute > ( ) ;
2008-03-14 12:12:50 +03:00
#if ! COMPACT_FRAMEWORK
2006-10-09 16:32:33 +04:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( mod ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofJavaModuleAttribute ) )
{
IList < CustomAttributeTypedArgument > args = cad . ConstructorArguments ;
if ( args . Count = = 0 )
{
attrs . Add ( new JavaModuleAttribute ( ) ) ;
}
else
{
attrs . Add ( new JavaModuleAttribute ( DecodeArray < string > ( args [ 0 ] ) ) ) ;
}
}
}
2008-03-14 12:12:50 +03:00
#endif
2006-10-09 16:32:33 +04:00
return attrs . ToArray ( ) ;
}
2006-10-09 12:29:42 +04:00
}
2005-12-07 12:06:32 +03:00
internal static bool IsNoPackagePrefix ( Type type )
{
return IsDefined ( type , typeofNoPackagePrefixAttribute ) | | IsDefined ( type . Assembly , typeofNoPackagePrefixAttribute ) ;
}
2009-02-04 09:51:40 +03:00
internal static EnclosingMethodAttribute GetEnclosingMethodAttribute ( Type type )
{
if ( type . Assembly . ReflectionOnly )
{
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( type ) )
{
if ( MatchTypes ( cad . Constructor . DeclaringType , typeofEnclosingMethodAttribute ) )
{
return new EnclosingMethodAttribute ( ( string ) cad . ConstructorArguments [ 0 ] . Value , ( string ) cad . ConstructorArguments [ 1 ] . Value , ( string ) cad . ConstructorArguments [ 2 ] . Value ) ;
}
}
}
else
{
object [ ] attr = type . GetCustomAttributes ( typeof ( EnclosingMethodAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( EnclosingMethodAttribute ) attr [ 0 ] ;
}
}
return null ;
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER & & ! COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static void SetRemappedClass ( AssemblyBuilder assemblyBuilder , string name , Type shadowType )
{
ConstructorInfo remappedClassAttribute = typeofRemappedClassAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( Type ) } ) ;
assemblyBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( remappedClassAttribute , new object [ ] { name , shadowType } ) ) ;
}
internal static void SetRemappedType ( TypeBuilder typeBuilder , Type shadowType )
{
ConstructorInfo remappedTypeAttribute = typeofRemappedTypeAttribute . GetConstructor ( new Type [ ] { typeof ( Type ) } ) ;
typeBuilder . SetCustomAttribute ( new CustomAttributeBuilder ( remappedTypeAttribute , new object [ ] { shadowType } ) ) ;
}
internal static void SetRemappedInterfaceMethod ( TypeBuilder typeBuilder , string name , string mappedTo )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofRemappedInterfaceMethodAttribute . GetConstructor ( new Type [ ] { typeof ( string ) , typeof ( string ) } ) , new object [ ] { name , mappedTo } ) ;
typeBuilder . SetCustomAttribute ( cab ) ;
}
internal static void SetExceptionIsUnsafeForMapping ( TypeBuilder typeBuilder )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( typeofExceptionIsUnsafeForMappingAttribute . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
typeBuilder . SetCustomAttribute ( cab ) ;
}
internal static void SetConstantValue ( FieldBuilder field , object constantValue )
{
2007-04-05 16:50:59 +04:00
CustomAttributeBuilder constantValueAttrib ;
try
{
constantValueAttrib = new CustomAttributeBuilder ( typeofConstantValueAttribute . GetConstructor ( new Type [ ] { constantValue . GetType ( ) } ) , new object [ ] { constantValue } ) ;
}
catch ( OverflowException )
{
// FXBUG for char values > 32K .NET (1.1 and 2.0) throws an exception (because it tries to convert to Int16)
if ( constantValue is char )
{
// we use the int constant value instead, the stub generator can handle that
constantValueAttrib = new CustomAttributeBuilder ( typeofConstantValueAttribute . GetConstructor ( new Type [ ] { typeof ( int ) } ) , new object [ ] { ( int ) ( char ) constantValue } ) ;
}
else
{
throw ;
}
}
2005-12-07 12:06:32 +03:00
field . SetCustomAttribute ( constantValueAttrib ) ;
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER && !COMPACT_FRAMEWORK
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
abstract class Annotation
{
2006-04-20 11:30:59 +04:00
// NOTE this method returns null if the type could not be found
2006-06-15 16:29:11 +04:00
// or if the type is not a Custom Attribute and we're not in the static compiler
2006-04-20 11:30:59 +04:00
internal static Annotation Load ( ClassLoaderWrapper loader , object [ ] def )
{
Debug . Assert ( def [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ANNOTATION ) ) ;
string annotationClass = ( string ) def [ 1 ] ;
2006-06-15 16:29:11 +04:00
#if ! STATIC_COMPILER
2007-04-15 12:01:19 +04:00
if ( ! annotationClass . EndsWith ( "$Annotation;" )
& & ! annotationClass . EndsWith ( "$Annotation$__ReturnValue;" )
& & ! annotationClass . EndsWith ( "$Annotation$__Multiple;" ) )
2006-06-15 16:29:11 +04:00
{
// we don't want to try to load an annotation in dynamic mode,
// unless it is a .NET custom attribute (which can affect runtime behavior)
return null ;
}
#endif
2006-04-20 11:30:59 +04:00
try
{
TypeWrapper annot = loader . RetTypeWrapperFromSig ( annotationClass . Replace ( '/' , '.' ) ) ;
return annot . Annotation ;
}
2007-07-25 20:28:20 +04:00
#if STATIC_COMPILER
catch ( ClassNotFoundException x )
{
StaticCompiler . IssueMessage ( Message . ClassNotFound , x . Message ) ;
return null ;
}
#endif
catch ( RetargetableJavaException )
2006-04-20 11:30:59 +04:00
{
Tracer . Warning ( Tracer . Compiler , "Unable to load annotation class {0}" , annotationClass ) ;
return null ;
}
}
2006-04-23 14:46:51 +04:00
internal static bool HasRetentionPolicyRuntime ( object [ ] annotations )
{
if ( annotations ! = null )
{
foreach ( object [ ] def in annotations )
{
if ( def [ 1 ] . Equals ( "Ljava/lang/annotation/Retention;" ) )
{
for ( int i = 2 ; i < def . Length ; i + = 2 )
{
if ( def [ i ] . Equals ( "value" ) )
{
object [ ] val = def [ i + 1 ] as object [ ] ;
if ( val ! = null
& & val . Length = = 3
& & val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ENUM )
& & val [ 1 ] . Equals ( "Ljava/lang/annotation/RetentionPolicy;" )
& & val [ 2 ] . Equals ( "RUNTIME" ) )
{
return true ;
}
}
}
}
}
}
return false ;
}
2008-02-09 20:37:38 +03:00
protected static object QualifyClassNames ( ClassLoaderWrapper loader , object annotation )
{
bool copy = false ;
object [ ] def = ( object [ ] ) annotation ;
for ( int i = 3 ; i < def . Length ; i + = 2 )
{
object [ ] val = def [ i ] as object [ ] ;
if ( val ! = null )
{
object [ ] newval = ValueQualifyClassNames ( loader , val ) ;
if ( newval ! = val )
{
if ( ! copy )
{
copy = true ;
object [ ] newdef = new object [ def . Length ] ;
Array . Copy ( def , newdef , def . Length ) ;
def = newdef ;
}
def [ i ] = newval ;
}
}
}
return def ;
}
private static object [ ] ValueQualifyClassNames ( ClassLoaderWrapper loader , object [ ] val )
{
if ( val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ANNOTATION ) )
{
return ( object [ ] ) QualifyClassNames ( loader , val ) ;
}
else if ( val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_CLASS ) )
{
string sig = ( string ) val [ 1 ] ;
if ( sig . StartsWith ( "L" ) )
{
TypeWrapper tw = loader . LoadClassByDottedNameFast ( sig . Substring ( 1 , sig . Length - 2 ) . Replace ( '/' , '.' ) ) ;
if ( tw ! = null )
{
return new object [ ] { AnnotationDefaultAttribute . TAG_CLASS , "L" + tw . TypeAsBaseType . AssemblyQualifiedName . Replace ( '.' , '/' ) + ";" } ;
}
}
return val ;
}
else if ( val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ENUM ) )
{
string sig = ( string ) val [ 1 ] ;
TypeWrapper tw = loader . LoadClassByDottedNameFast ( sig . Substring ( 1 , sig . Length - 2 ) . Replace ( '/' , '.' ) ) ;
if ( tw ! = null )
{
return new object [ ] { AnnotationDefaultAttribute . TAG_ENUM , "L" + tw . TypeAsBaseType . AssemblyQualifiedName . Replace ( '.' , '/' ) + ";" , val [ 2 ] } ;
}
return val ;
}
else if ( val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ARRAY ) )
{
bool copy = false ;
for ( int i = 1 ; i < val . Length ; i + + )
{
object [ ] nval = val [ i ] as object [ ] ;
if ( nval ! = null )
{
object newnval = ValueQualifyClassNames ( loader , nval ) ;
if ( newnval ! = nval )
{
if ( ! copy )
{
copy = true ;
object [ ] newval = new object [ val . Length ] ;
Array . Copy ( val , newval , val . Length ) ;
val = newval ;
}
val [ i ] = newnval ;
}
}
}
return val ;
}
else
{
throw new InvalidOperationException ( ) ;
}
}
2007-04-12 13:27:17 +04:00
internal abstract void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation ) ;
internal abstract void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation ) ;
internal abstract void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation ) ;
internal abstract void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation ) ;
internal abstract void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation ) ;
internal abstract void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation ) ;
2008-04-14 09:13:41 +04:00
internal abstract void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation ) ;
2007-04-15 12:01:19 +04:00
internal virtual void ApplyReturnValue ( ClassLoaderWrapper loader , MethodBuilder mb , ref ParameterBuilder pb , object annotation )
{
}
2005-11-01 17:01:42 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-11-01 17:01:42 +03:00
2006-04-05 12:18:58 +04:00
[Flags]
enum TypeFlags : ushort
{
HasIncompleteInterfaceImplementation = 1 ,
InternalAccess = 2 ,
2006-08-21 09:15:51 +04:00
HasStaticInitializer = 4 ,
VerifyError = 8 ,
ClassFormatError = 16 ,
2007-02-19 14:31:38 +03:00
HasUnsupportedAbstractMethods = 32 ,
2006-04-05 12:18:58 +04:00
}
2006-04-10 13:09:09 +04:00
internal abstract class TypeWrapper
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
private readonly string name ; // java name (e.g. java.lang.Object)
private readonly Modifiers modifiers ;
2006-04-05 12:18:58 +04:00
private TypeFlags flags ;
2005-06-01 13:49:30 +04:00
private MethodWrapper [ ] methods ;
private FieldWrapper [ ] fields ;
private readonly TypeWrapper baseWrapper ;
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2006-03-23 14:57:41 +03:00
private object classObject ;
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
internal static readonly TypeWrapper [ ] EmptyArray = new TypeWrapper [ 0 ] ;
internal const Modifiers UnloadableModifiersHack = Modifiers . Final | Modifiers . Interface | Modifiers . Private ;
internal const Modifiers VerifierTypeModifiersHack = Modifiers . Final | Modifiers . Interface ;
2003-07-31 16:49:29 +04:00
2006-03-23 14:57:41 +03:00
internal TypeWrapper ( Modifiers modifiers , string name , TypeWrapper baseWrapper )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Profiler . Count ( "TypeWrapper" ) ;
// class name should be dotted or null for primitives
Debug . Assert ( name = = null | | name . IndexOf ( '/' ) < 0 ) ;
2003-08-01 16:12:08 +04:00
2005-06-01 13:49:30 +04:00
this . modifiers = modifiers ;
2005-07-20 13:42:11 +04:00
this . name = name = = null ? null : String . Intern ( name ) ;
2005-06-01 13:49:30 +04:00
this . baseWrapper = baseWrapper ;
2006-03-23 14:57:41 +03:00
}
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2006-03-23 14:57:41 +03:00
internal void SetClassObject ( object classObject )
{
this . classObject = classObject ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal object ClassObject
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-09-12 13:57:36 +04:00
Debug . Assert ( ! IsUnloadable & & ! IsVerifierType ) ;
2009-02-24 07:42:20 +03:00
if ( classObject = = null )
{
LazyInitClass ( ) ;
}
return classObject ;
}
}
private void LazyInitClass ( )
{
lock ( this )
{
if ( classObject = = null )
2006-03-23 14:57:41 +03:00
{
2006-07-06 17:53:51 +04:00
#if ! COMPACT_FRAMEWORK
2009-02-24 07:42:20 +03:00
// DynamicTypeWrapper should haved already had SetClassObject explicitly
Debug . Assert ( ! ( this is DynamicTypeWrapper ) ) ;
2006-07-06 17:53:51 +04:00
#endif // !COMPACT_FRAMEWORK
2008-08-06 16:22:06 +04:00
#if ! FIRST_PASS
2009-02-24 07:42:20 +03:00
java . lang . Class clazz = java . lang . Class . newClass ( ) ;
2009-03-02 09:30:13 +03:00
#if __MonoCS__
2009-02-24 07:42:20 +03:00
SetTypeWrapperHack ( ref clazz . typeWrapper , this ) ;
2009-03-02 09:30:13 +03:00
#else
clazz . typeWrapper = this ;
#endif
2009-02-25 08:00:53 +03:00
// MONOBUG Interlocked.Exchange is broken on Mono, so we use CompareExchange
System . Threading . Interlocked . CompareExchange ( ref classObject , clazz , null ) ;
2007-12-19 14:28:09 +03:00
#endif
2006-03-23 14:57:41 +03:00
}
2005-06-01 13:49:30 +04:00
}
2004-10-19 17:43:55 +04:00
}
2003-05-13 00:00:15 +04:00
2009-03-02 09:30:13 +03:00
#if __MonoCS__
2008-05-20 11:36:50 +04:00
// MONOBUG this method is to work around an mcs bug
internal static void SetTypeWrapperHack < T > ( ref T field , TypeWrapper type )
{
field = ( T ) ( object ) type ;
}
2009-03-02 09:30:13 +03:00
#endif
2008-05-20 11:36:50 +04:00
2006-03-27 17:59:59 +04:00
internal static TypeWrapper FromClass ( object classObject )
{
2007-12-19 14:28:09 +03:00
#if FIRST_PASS
return null ;
2008-08-06 16:22:06 +04:00
#else
2008-05-20 11:36:50 +04:00
// MONOBUG redundant cast to workaround mcs bug
return ( TypeWrapper ) ( object ) ( ( java . lang . Class ) classObject ) . typeWrapper ;
2007-12-19 14:28:09 +03:00
#endif
2006-03-27 17:59:59 +04:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2006-03-27 17:59:59 +04:00
2005-06-01 13:49:30 +04:00
public override string ToString ( )
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return GetType ( ) . Name + "[" + name + "]" ;
2004-12-21 17:59:29 +03:00
}
2005-06-01 13:49:30 +04:00
// For UnloadableTypeWrapper it tries to load the type through the specified loader
// and if that fails it throw a NoClassDefFoundError (not a java.lang.NoClassDefFoundError),
// for all other types this is a no-op.
internal virtual TypeWrapper EnsureLoadable ( ClassLoaderWrapper loader )
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return this ;
2004-12-21 17:59:29 +03:00
}
2005-02-23 15:56:15 +03:00
2005-06-01 13:49:30 +04:00
internal bool HasIncompleteInterfaceImplementation
2003-05-13 00:00:15 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return ( flags & TypeFlags . HasIncompleteInterfaceImplementation ) ! = 0 | | ( baseWrapper ! = null & & baseWrapper . HasIncompleteInterfaceImplementation ) ;
2005-06-01 13:49:30 +04:00
}
set
{
2006-04-05 12:18:58 +04:00
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . HasIncompleteInterfaceImplementation ;
}
else
{
flags & = ~ TypeFlags . HasIncompleteInterfaceImplementation ;
}
2005-06-01 13:49:30 +04:00
}
2003-05-13 00:00:15 +04:00
}
2007-02-19 14:31:38 +03:00
internal bool HasUnsupportedAbstractMethods
{
get
{
foreach ( TypeWrapper iface in this . Interfaces )
{
if ( iface . HasUnsupportedAbstractMethods )
{
return true ;
}
}
return ( flags & TypeFlags . HasUnsupportedAbstractMethods ) ! = 0 | | ( baseWrapper ! = null & & baseWrapper . HasUnsupportedAbstractMethods ) ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . HasUnsupportedAbstractMethods ;
}
else
{
flags & = ~ TypeFlags . HasUnsupportedAbstractMethods ;
}
}
}
2005-06-01 13:49:30 +04:00
internal virtual bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return ( flags & TypeFlags . HasStaticInitializer ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . HasStaticInitializer ;
}
else
{
flags & = ~ TypeFlags . HasStaticInitializer ;
}
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2006-08-21 09:15:51 +04:00
internal bool HasVerifyError
{
get
{
return ( flags & TypeFlags . VerifyError ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . VerifyError ;
}
else
{
flags & = ~ TypeFlags . VerifyError ;
}
}
}
internal bool HasClassFormatError
{
get
{
return ( flags & TypeFlags . ClassFormatError ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . ClassFormatError ;
}
else
{
flags & = ~ TypeFlags . ClassFormatError ;
}
}
}
2008-03-03 10:05:19 +03:00
internal virtual bool IsFakeTypeContainer
{
get
{
return false ;
}
}
2009-02-04 11:10:24 +03:00
internal bool IsFakeNestedType
{
get
{
TypeWrapper outer = this . DeclaringTypeWrapper ;
return outer ! = null & & outer . IsFakeTypeContainer ;
}
}
2005-06-01 13:49:30 +04:00
// a ghost is an interface that appears to be implemented by a .NET type
// (e.g. System.String (aka java.lang.String) appears to implement java.lang.CharSequence,
// so java.lang.CharSequence is a ghost)
internal virtual bool IsGhost
2003-07-31 16:49:29 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2003-07-31 16:49:29 +04:00
}
2005-06-01 13:49:30 +04:00
// is this an array type of which the ultimate element type is a ghost?
internal bool IsGhostArray
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2008-06-18 14:23:37 +04:00
return ! IsUnloadable & & IsArray & & ( ElementTypeWrapper . IsGhost | | ElementTypeWrapper . IsGhostArray ) ;
2005-06-01 13:49:30 +04:00
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual FieldInfo GhostRefField
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( ) ;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsRemapped
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsArray
2003-03-21 16:41:43 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name ! = null & & name [ 0 ] = = '[' ;
}
2003-03-21 16:41:43 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE for non-array types this returns 0
internal int ArrayRank
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
int i = 0 ;
if ( name ! = null )
2003-06-20 17:46:13 +04:00
{
2005-06-01 13:49:30 +04:00
while ( name [ i ] = = '[' )
{
i + + ;
}
2003-06-20 17:46:13 +04:00
}
2005-06-01 13:49:30 +04:00
return i ;
2003-01-06 16:56:37 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal bool IsNonPrimitiveValueType
2003-04-14 13:41:58 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return this ! = VerifierTypeWrapper . Null & & ! IsPrimitive & & ! IsGhost & & TypeAsTBD . IsValueType ;
}
2003-04-14 13:41:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal bool IsPrimitive
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name = = null ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsWidePrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return this = = PrimitiveTypeWrapper . LONG | | this = = PrimitiveTypeWrapper . DOUBLE ;
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsIntOnStackPrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name = = null & &
( this = = PrimitiveTypeWrapper . BOOLEAN | |
this = = PrimitiveTypeWrapper . BYTE | |
this = = PrimitiveTypeWrapper . CHAR | |
this = = PrimitiveTypeWrapper . SHORT | |
this = = PrimitiveTypeWrapper . INT ) ;
}
2003-11-17 15:01:50 +03:00
}
2006-10-19 10:12:48 +04:00
private static bool IsJavaPrimitive ( Type type )
{
return type = = PrimitiveTypeWrapper . BOOLEAN . TypeAsTBD
| | type = = PrimitiveTypeWrapper . BYTE . TypeAsTBD
| | type = = PrimitiveTypeWrapper . CHAR . TypeAsTBD
| | type = = PrimitiveTypeWrapper . DOUBLE . TypeAsTBD
| | type = = PrimitiveTypeWrapper . FLOAT . TypeAsTBD
| | type = = PrimitiveTypeWrapper . INT . TypeAsTBD
| | type = = PrimitiveTypeWrapper . LONG . TypeAsTBD
| | type = = PrimitiveTypeWrapper . SHORT . TypeAsTBD
| | type = = PrimitiveTypeWrapper . VOID . TypeAsTBD ;
}
2008-03-04 10:28:00 +03:00
internal bool IsBoxedPrimitive
{
get
{
return ! IsPrimitive & & IsJavaPrimitive ( TypeAsSignatureType ) ;
}
}
2006-10-04 13:03:18 +04:00
internal bool IsErasedOrBoxedPrimitiveOrRemapped
2006-08-26 17:00:50 +04:00
{
get
{
2008-03-03 10:05:19 +03:00
bool erased = IsUnloadable | | IsGhostArray ;
2008-03-04 10:28:00 +03:00
return erased | | IsBoxedPrimitive | | ( IsRemapped & & this is DotNetTypeWrapper ) ;
2006-08-26 17:00:50 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal bool IsUnloadable
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note unloadable classes
return modifiers = = UnloadableModifiersHack ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsVerifierType
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note verifier types
return modifiers = = VerifierTypeModifiersHack ;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsMapUnsafeException
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal Modifiers Modifiers
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// since for inner classes, the modifiers returned by Class.getModifiers are different from the actual
// modifiers (as used by the VM access control mechanism), we have this additional property
internal virtual Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers ;
}
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal bool IsInternal
{
get
{
return ( flags & TypeFlags . InternalAccess ) ! = 0 ;
}
set
{
// TODO do we need locking here?
if ( value )
{
flags | = TypeFlags . InternalAccess ;
}
else
{
flags & = ~ TypeFlags . InternalAccess ;
}
}
}
2005-06-01 13:49:30 +04:00
internal bool IsPublic
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return ( modifiers & Modifiers . Public ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsAbstract
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// interfaces don't need to marked abstract explicitly (and javac 1.1 didn't do it)
return ( modifiers & ( Modifiers . Abstract | Modifiers . Interface ) ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsFinal
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return ( modifiers & Modifiers . Final ) ! = 0 ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsInterface
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug . Assert ( ! IsUnloadable & & ! IsVerifierType ) ;
return ( modifiers & Modifiers . Interface ) ! = 0 ;
}
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
// this exists because interfaces and arrays of interfaces are treated specially
// by the verifier, interfaces don't have a common base (other than java.lang.Object)
// so any object reference or object array reference can be used where an interface
// or interface array reference is expected (the compiler will insert the required casts).
internal bool IsInterfaceOrInterfaceArray
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = this ;
while ( tw . IsArray )
{
tw = tw . ElementTypeWrapper ;
}
return tw . IsInterface ;
2003-08-29 14:14:08 +04:00
}
}
2006-03-23 14:57:41 +03:00
internal abstract ClassLoaderWrapper GetClassLoader ( ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal FieldWrapper GetFieldWrapper ( string fieldName , string fieldSig )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( fields = = null )
{
LazyPublishMembers ( ) ;
}
}
foreach ( FieldWrapper fw in fields )
{
if ( fw . Name = = fieldName & & fw . Signature = = fieldSig )
{
return fw ;
}
}
foreach ( TypeWrapper iface in this . Interfaces )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
FieldWrapper fw = iface . GetFieldWrapper ( fieldName , fieldSig ) ;
if ( fw ! = null )
{
return fw ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
if ( baseWrapper ! = null )
{
return baseWrapper . GetFieldWrapper ( fieldName , fieldSig ) ;
}
return null ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
protected virtual void LazyPublishMembers ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( methods = = null )
{
methods = MethodWrapper . EmptyArray ;
}
if ( fields = = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
fields = FieldWrapper . EmptyArray ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper [ ] GetMethods ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( methods = = null )
{
LazyPublishMembers ( ) ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return methods ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal FieldWrapper [ ] GetFields ( )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( fields = = null )
{
LazyPublishMembers ( ) ;
}
}
return fields ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper GetMethodWrapper ( string name , string sig , bool inherit )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
{
if ( methods = = null )
{
LazyPublishMembers ( ) ;
}
}
2006-05-03 12:52:52 +04:00
// MemberWrapper interns the name and sig so we can use ref equality
// profiling has shown this to be more efficient
string _name = String . IsInterned ( name ) ;
string _sig = String . IsInterned ( sig ) ;
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in methods )
{
2006-05-03 12:52:52 +04:00
// NOTE we can use ref equality, because names and signatures are
// always interned by MemberWrapper
if ( ReferenceEquals ( mw . Name , _name ) & & ReferenceEquals ( mw . Signature , _sig ) )
2005-06-01 13:49:30 +04:00
{
return mw ;
}
}
if ( inherit & & baseWrapper ! = null )
{
return baseWrapper . GetMethodWrapper ( name , sig , inherit ) ;
}
return null ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetMethods ( MethodWrapper [ ] methods )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( methods ! = null ) ;
this . methods = methods ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetFields ( FieldWrapper [ ] fields )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( fields ! = null ) ;
this . fields = fields ;
2005-01-03 11:26:21 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal string Name
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return name ;
2005-01-03 11:26:21 +03:00
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// the name of the type as it appears in a Java signature string (e.g. "Ljava.lang.Object;" or "I")
internal virtual string SigName
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return "L" + this . Name + ";" ;
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
// returns true iff wrapper is allowed to access us
internal bool IsAccessibleFrom ( TypeWrapper wrapper )
2005-01-03 11:26:21 +03:00
{
2006-04-05 12:18:58 +04:00
return IsPublic
2009-02-10 10:24:30 +03:00
| | ( IsInternal & & InternalsVisibleTo ( wrapper ) )
2007-12-17 13:59:02 +03:00
| | IsPackageAccessibleFrom ( wrapper ) ;
2002-12-18 19:00:25 +03:00
}
2009-02-10 10:24:30 +03:00
internal bool InternalsVisibleTo ( TypeWrapper wrapper )
{
return GetClassLoader ( ) . InternalsVisibleToImpl ( this , wrapper ) ;
}
2007-12-17 13:59:02 +03:00
internal bool IsPackageAccessibleFrom ( TypeWrapper wrapper )
2002-12-18 19:00:25 +03:00
{
2009-02-10 10:24:30 +03:00
return MatchingPackageNames ( name , wrapper . name ) & & InternalsVisibleTo ( wrapper ) ;
2008-12-23 10:12:51 +03:00
}
private static bool MatchingPackageNames ( string name1 , string name2 )
{
int index1 = name1 . LastIndexOf ( '.' ) ;
int index2 = name2 . LastIndexOf ( '.' ) ;
if ( index1 = = - 1 & & index2 = = - 1 )
2005-06-01 13:49:30 +04:00
{
2008-12-23 10:12:51 +03:00
return true ;
2005-06-01 13:49:30 +04:00
}
2008-12-23 10:12:51 +03:00
// for array types we need to skip the brackets
int skip1 = 0 ;
int skip2 = 0 ;
while ( name1 [ skip1 ] = = '[' )
{
skip1 + + ;
}
while ( name2 [ skip2 ] = = '[' )
{
skip2 + + ;
}
if ( skip1 > 0 )
{
// skip over the L that follows the brackets
skip1 + + ;
}
if ( skip2 > 0 )
{
// skip over the L that follows the brackets
skip2 + + ;
}
if ( ( index1 - skip1 ) ! = ( index2 - skip2 ) )
{
return false ;
}
return String . CompareOrdinal ( name1 , skip1 , name2 , skip2 , index1 - skip1 ) = = 0 ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal abstract Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-08-21 14:06:34 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal virtual TypeBuilder TypeAsBuilder
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
TypeBuilder typeBuilder = TypeAsTBD as TypeBuilder ;
Debug . Assert ( typeBuilder ! = null ) ;
return typeBuilder ;
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal Type TypeAsSignatureType
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
if ( IsUnloadable )
{
return typeof ( object ) ;
}
if ( IsGhostArray )
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper . MakeArrayType ( typeof ( object ) , ArrayRank ) ;
2005-06-01 13:49:30 +04:00
}
return TypeAsTBD ;
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual Type TypeAsBaseType
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
}
internal Type TypeAsLocalOrStackType
{
get
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable | | IsGhost )
{
return typeof ( object ) ;
}
if ( IsNonPrimitiveValueType )
{
// return either System.ValueType or System.Enum
return TypeAsTBD . BaseType ;
}
if ( IsGhostArray )
2003-08-12 17:09:31 +04:00
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper . MakeArrayType ( typeof ( object ) , ArrayRank ) ;
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-08-12 17:09:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
/** <summary>Use this if the type is used as an array or array element</summary> */
internal Type TypeAsArrayType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable | | IsGhost )
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof ( object ) ;
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
if ( IsGhostArray )
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper . MakeArrayType ( typeof ( object ) , ArrayRank ) ;
2005-06-01 13:49:30 +04:00
}
return TypeAsTBD ;
2003-09-10 18:58:19 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal Type TypeAsExceptionType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof ( Exception ) ;
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD ;
2003-10-17 12:08:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper BaseTypeWrapper
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return baseWrapper ;
2003-09-10 18:58:19 +04:00
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper ElementTypeWrapper
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug . Assert ( ! this . IsUnloadable ) ;
Debug . Assert ( this = = VerifierTypeWrapper . Null | | this . IsArray ) ;
if ( this = = VerifierTypeWrapper . Null )
{
return VerifierTypeWrapper . Null ;
}
// TODO consider caching the element type
switch ( name [ 1 ] )
{
case '[' :
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader ( ) . LoadClassByDottedNameFast ( name . Substring ( 1 ) ) ;
2005-06-01 13:49:30 +04:00
case 'L' :
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader ( ) . LoadClassByDottedNameFast ( name . Substring ( 2 , name . Length - 3 ) ) ;
2005-06-01 13:49:30 +04:00
case 'Z' :
return PrimitiveTypeWrapper . BOOLEAN ;
case 'B' :
return PrimitiveTypeWrapper . BYTE ;
case 'S' :
return PrimitiveTypeWrapper . SHORT ;
case 'C' :
return PrimitiveTypeWrapper . CHAR ;
case 'I' :
return PrimitiveTypeWrapper . INT ;
case 'J' :
return PrimitiveTypeWrapper . LONG ;
case 'F' :
return PrimitiveTypeWrapper . FLOAT ;
case 'D' :
return PrimitiveTypeWrapper . DOUBLE ;
default :
throw new InvalidOperationException ( name ) ;
}
}
2002-12-18 19:00:25 +03:00
}
2006-07-21 14:18:13 +04:00
internal TypeWrapper MakeArrayType ( int rank )
2003-01-06 16:56:37 +03:00
{
2005-08-19 13:08:43 +04:00
Debug . Assert ( rank ! = 0 ) ;
2005-06-01 13:49:30 +04:00
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
return GetClassLoader ( ) . LoadClassByDottedNameFast ( new String ( '[' , rank ) + this . SigName ) ;
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool ImplementsInterface ( TypeWrapper interfaceWrapper )
{
TypeWrapper typeWrapper = this ;
while ( typeWrapper ! = null )
2003-06-13 19:13:20 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] interfaces = typeWrapper . Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
{
if ( interfaces [ i ] = = interfaceWrapper )
{
return true ;
}
if ( interfaces [ i ] . ImplementsInterface ( interfaceWrapper ) )
{
return true ;
}
}
typeWrapper = typeWrapper . BaseTypeWrapper ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
return false ;
2003-01-06 16:56:37 +03:00
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsSubTypeOf ( TypeWrapper baseType )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// make sure IsSubTypeOf isn't used on primitives
Debug . Assert ( ! this . IsPrimitive ) ;
Debug . Assert ( ! baseType . IsPrimitive ) ;
// can't be used on Unloadable
Debug . Assert ( ! this . IsUnloadable ) ;
Debug . Assert ( ! baseType . IsUnloadable ) ;
if ( baseType . IsInterface )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( baseType = = this )
2002-12-18 19:00:25 +03:00
{
return true ;
}
2005-06-01 13:49:30 +04:00
return ImplementsInterface ( baseType ) ;
}
// NOTE this isn't just an optimization, it is also required when this is an interface
if ( baseType = = CoreClasses . java . lang . Object . Wrapper )
{
return true ;
}
TypeWrapper subType = this ;
while ( subType ! = baseType )
{
subType = subType . BaseTypeWrapper ;
if ( subType = = null )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return false ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
return true ;
2002-12-18 19:00:25 +03:00
}
2003-01-07 17:53:17 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsAssignableTo ( TypeWrapper wrapper )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( this = = wrapper )
2002-12-18 19:00:25 +03:00
{
return true ;
}
2005-06-01 13:49:30 +04:00
if ( this . IsPrimitive | | wrapper . IsPrimitive )
2002-12-18 19:00:25 +03:00
{
return false ;
}
2005-06-01 13:49:30 +04:00
if ( this = = VerifierTypeWrapper . Null )
{
return true ;
}
if ( wrapper . IsInterface )
{
return ImplementsInterface ( wrapper ) ;
}
int rank1 = this . ArrayRank ;
int rank2 = wrapper . ArrayRank ;
if ( rank1 > 0 & & rank2 > 0 )
{
rank1 - - ;
rank2 - - ;
TypeWrapper elem1 = this . ElementTypeWrapper ;
TypeWrapper elem2 = wrapper . ElementTypeWrapper ;
while ( rank1 ! = 0 & & rank2 ! = 0 )
{
elem1 = elem1 . ElementTypeWrapper ;
elem2 = elem2 . ElementTypeWrapper ;
rank1 - - ;
rank2 - - ;
}
2007-07-22 08:45:22 +04:00
return ( ! elem1 . IsNonPrimitiveValueType & & elem1 . IsSubTypeOf ( elem2 ) ) | | ( rank1 = = rank2 & & elem2 . IsGhost & & elem1 = = CoreClasses . java . lang . Object . Wrapper ) ;
2005-06-01 13:49:30 +04:00
}
return this . IsSubTypeOf ( wrapper ) ;
2002-12-18 19:00:25 +03:00
}
2008-08-06 09:48:52 +04:00
#if ! STATIC_COMPILER
2007-05-31 11:12:56 +04:00
internal bool IsInstance ( object obj )
{
if ( obj ! = null )
{
TypeWrapper thisWrapper = this ;
TypeWrapper objWrapper = IKVM . NativeCode . ikvm . runtime . Util . GetTypeWrapperFromObject ( obj ) ;
return objWrapper . IsAssignableTo ( thisWrapper ) ;
}
return false ;
}
2008-08-06 09:48:52 +04:00
#endif
2007-05-31 11:12:56 +04:00
2005-06-01 13:49:30 +04:00
internal abstract TypeWrapper [ ] Interfaces
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper [ ] InnerClasses
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper DeclaringTypeWrapper
2004-02-02 12:46:13 +03:00
{
2005-06-01 13:49:30 +04:00
get ;
2004-02-02 12:46:13 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-05 12:40:54 +04:00
internal abstract void Finish ( ) ;
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private void ImplementInterfaceMethodStubImpl ( MethodWrapper ifmethod , TypeBuilder typeBuilder , DynamicTypeWrapper wrapper )
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
// we're mangling the name to prevent subclasses from accidentally overriding this method and to
// prevent clashes with overloaded method stubs that are erased to the same signature (e.g. unloadable types and ghost arrays)
2006-11-01 11:55:25 +03:00
// HACK the signature and name are the wrong way around to work around a C++/CLI bug (apparantely it looks looks at the last n
// characters of the method name, or something bizarre like that)
// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=234167
string mangledName = this . Name + "/" + ifmethod . Signature + ifmethod . Name ;
2005-06-01 13:49:30 +04:00
MethodWrapper mce = null ;
TypeWrapper lookup = wrapper ;
while ( lookup ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
mce = lookup . GetMethodWrapper ( ifmethod . Name , ifmethod . Signature , true ) ;
if ( mce = = null | | ! mce . IsStatic )
{
break ;
}
lookup = mce . DeclaringType . BaseTypeWrapper ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
if ( mce ! = null )
2002-12-18 19:00:25 +03:00
{
2008-05-31 19:20:29 +04:00
Debug . Assert ( ! mce . HasCallerID ) ;
2005-08-02 12:44:55 +04:00
if ( mce . DeclaringType ! = wrapper )
{
// check the loader constraints
bool error = false ;
if ( mce . ReturnType ! = ifmethod . ReturnType )
{
// TODO handle unloadable
error = true ;
}
TypeWrapper [ ] mceparams = mce . GetParameters ( ) ;
TypeWrapper [ ] ifparams = ifmethod . GetParameters ( ) ;
for ( int i = 0 ; i < mceparams . Length ; i + + )
{
if ( mceparams [ i ] ! = ifparams [ i ] )
{
// TODO handle unloadable
error = true ;
break ;
}
}
if ( error )
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-08-02 12:44:55 +04:00
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( mb ) , "java.lang.LinkageError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
2005-08-02 12:44:55 +04:00
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
return ;
}
}
2005-06-01 13:49:30 +04:00
if ( mce . IsMirandaMethod & & mce . DeclaringType = = wrapper )
{
// Miranda methods already have a methodimpl (if needed) to implement the correct interface method
}
else if ( ! mce . IsPublic )
{
// NOTE according to the ECMA spec it isn't legal for a privatescope method to be virtual, but this works and
// it makes sense, so I hope the spec is wrong
// UPDATE unfortunately, according to Serge Lidin the spec is correct, and it is not allowed to have virtual privatescope
// methods. Sigh! So I have to use private methods and mangle the name
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( mb ) , "java.lang.IllegalAccessError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
2005-06-01 13:49:30 +04:00
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
wrapper . HasIncompleteInterfaceImplementation = true ;
}
else if ( mce . GetMethod ( ) = = null | | mce . RealName ! = ifmethod . RealName )
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( mb ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
int argc = mce . GetParameters ( ) . Length ;
for ( int n = 0 ; n < argc ; n + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( n + 1 ) ) ;
}
mce . EmitCallvirt ( ilGenerator ) ;
ilGenerator . Emit ( OpCodes . Ret ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
}
2008-11-14 11:42:07 +03:00
else if ( ! ReflectUtil . IsSameAssembly ( mce . DeclaringType . TypeAsTBD , typeBuilder ) )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// NOTE methods inherited from base classes in a different assembly do *not* automatically implement
// interface methods, so we have to generate a stub here that doesn't do anything but call the base
// implementation
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( mb ) ;
2005-06-01 13:49:30 +04:00
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
int argc = mce . GetParameters ( ) . Length ;
for ( int n = 0 ; n < argc ; n + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( n + 1 ) ) ;
}
mce . EmitCallvirt ( ilGenerator ) ;
ilGenerator . Emit ( OpCodes . Ret ) ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
else
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! wrapper . IsAbstract )
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
// the type doesn't implement the interface method and isn't abstract either. The JVM allows this, but the CLR doesn't,
// so we have to create a stub method that throws an AbstractMethodError
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( mangledName , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final , ifmethod . ReturnTypeForDefineMethod , ifmethod . GetParametersForDefineMethod ( ) ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( mb ) , "java.lang.AbstractMethodError" , wrapper . Name + "." + ifmethod . Name + ifmethod . Signature ) ;
2005-06-01 13:49:30 +04:00
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) ifmethod . GetMethod ( ) ) ;
wrapper . HasIncompleteInterfaceImplementation = true ;
2002-12-29 19:27:00 +03:00
}
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
2008-08-15 16:01:06 +04:00
internal void ImplementInterfaceMethodStubs ( TypeBuilder typeBuilder , DynamicTypeWrapper wrapper , Dictionary < TypeWrapper , TypeWrapper > doneSet )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsInterface ) ;
2006-08-26 17:00:50 +04:00
// make sure we don't do the same method twice and dynamic only interfaces
// don't really exist, so there is no point in generating stub methods for
// them (nor can we).
2008-03-03 10:05:19 +03:00
if ( doneSet . ContainsKey ( this ) )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
doneSet . Add ( this , this ) ;
foreach ( MethodWrapper method in GetMethods ( ) )
{
2008-03-03 10:05:19 +03:00
if ( ! method . IsStatic & & ! method . IsDynamicOnly )
2005-06-01 13:49:30 +04:00
{
ImplementInterfaceMethodStubImpl ( method , typeBuilder , wrapper ) ;
}
}
TypeWrapper [ ] interfaces = Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
[Conditional("DEBUG")]
internal static void AssertFinished ( Type type )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
if ( type ! = null )
2003-02-22 15:28:12 +03:00
{
2007-01-16 13:14:47 +03:00
while ( type . HasElementType )
2005-06-01 13:49:30 +04:00
{
type = type . GetElementType ( ) ;
}
Debug . Assert ( ! ( type is TypeBuilder ) ) ;
2003-02-22 15:28:12 +03:00
}
}
2003-12-20 01:19:18 +03:00
2005-06-01 13:49:30 +04:00
internal void RunClassInit ( )
2005-02-02 18:11:26 +03:00
{
2007-09-24 17:06:30 +04:00
Type t = IsRemapped ? TypeAsBaseType : TypeAsTBD ;
2006-06-15 16:29:11 +04:00
if ( t ! = null )
{
System . Runtime . CompilerServices . RuntimeHelpers . RunClassConstructor ( t . TypeHandle ) ;
}
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal void EmitUnbox ( CodeEmitter ilgen )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsNonPrimitiveValueType ) ;
2005-12-19 18:12:49 +03:00
ilgen . LazyEmitUnboxSpecial ( this . TypeAsTBD ) ;
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
internal void EmitBox ( CodeEmitter ilgen )
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( this . IsNonPrimitiveValueType ) ;
2005-12-19 18:12:49 +03:00
ilgen . LazyEmitBox ( this . TypeAsTBD ) ;
2005-02-02 18:11:26 +03:00
}
2008-06-03 16:10:07 +04:00
internal void EmitConvSignatureTypeToStackType ( CodeEmitter ilgen )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsUnloadable )
2003-12-20 01:19:18 +03:00
{
}
2005-06-01 13:49:30 +04:00
else if ( this = = PrimitiveTypeWrapper . BYTE )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Conv_I1 ) ;
2004-03-08 18:18:47 +03:00
}
else if ( IsNonPrimitiveValueType )
{
2005-06-01 13:49:30 +04:00
EmitBox ( ilgen ) ;
}
else if ( IsGhost )
{
LocalBuilder local = ilgen . DeclareLocal ( TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Stloc , local ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldfld , GhostRefField ) ;
2004-03-08 18:18:47 +03:00
}
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE sourceType is optional and only used for interfaces,
// it is *not* used to automatically downcast
2008-06-03 16:10:07 +04:00
internal void EmitConvStackTypeToSignatureType ( CodeEmitter ilgen , TypeWrapper sourceType )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! IsUnloadable )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
LocalBuilder local1 = ilgen . DeclareLocal ( TypeAsLocalOrStackType ) ;
ilgen . Emit ( OpCodes . Stloc , local1 ) ;
LocalBuilder local2 = ilgen . DeclareLocal ( TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ldloca , local2 ) ;
ilgen . Emit ( OpCodes . Ldloc , local1 ) ;
ilgen . Emit ( OpCodes . Stfld , GhostRefField ) ;
ilgen . Emit ( OpCodes . Ldloca , local2 ) ;
ilgen . Emit ( OpCodes . Ldobj , TypeAsSignatureType ) ;
}
// because of the way interface merging works, any reference is valid
// for any interface reference
else if ( IsInterfaceOrInterfaceArray & & ( sourceType = = null | | sourceType . IsUnloadable | | ! sourceType . IsAssignableTo ( this ) ) )
{
EmitHelper . EmitAssertType ( ilgen , TypeAsTBD ) ;
Profiler . Count ( "InterfaceDownCast" ) ;
}
else if ( IsNonPrimitiveValueType )
{
EmitUnbox ( ilgen ) ;
}
2005-08-05 16:18:35 +04:00
else if ( sourceType ! = null & & sourceType . IsUnloadable )
{
ilgen . Emit ( OpCodes . Castclass , TypeAsSignatureType ) ;
}
2004-01-11 16:14:42 +03:00
}
}
2008-06-03 16:10:07 +04:00
internal virtual void EmitCheckcast ( TypeWrapper context , CodeEmitter ilgen )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
ilgen . Emit ( OpCodes . Dup ) ;
// TODO make sure we get the right "Cast" method and cache it
2007-11-06 11:54:52 +03:00
// NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
2005-06-01 13:49:30 +04:00
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen . Emit ( OpCodes . Call , TypeAsTBD . GetMethod ( "Cast" ) ) ;
ilgen . Emit ( OpCodes . Pop ) ;
}
else if ( IsGhostArray )
{
ilgen . Emit ( OpCodes . Dup ) ;
// TODO make sure we get the right "CastArray" method and cache it
2007-11-06 11:54:52 +03:00
// NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
2005-06-01 13:49:30 +04:00
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
TypeWrapper tw = this ;
int rank = 0 ;
while ( tw . IsArray )
{
rank + + ;
tw = tw . ElementTypeWrapper ;
}
ilgen . Emit ( OpCodes . Ldc_I4 , rank ) ;
ilgen . Emit ( OpCodes . Call , tw . TypeAsTBD . GetMethod ( "CastArray" ) ) ;
2007-11-06 11:54:52 +03:00
ilgen . Emit ( OpCodes . Castclass , ArrayTypeWrapper . MakeArrayType ( typeof ( object ) , rank ) ) ;
2005-06-01 13:49:30 +04:00
}
else
{
EmitHelper . Castclass ( ilgen , TypeAsTBD ) ;
}
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
internal virtual void EmitInstanceOf ( TypeWrapper context , CodeEmitter ilgen )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if ( IsGhost )
{
// TODO make sure we get the right "IsInstance" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen . Emit ( OpCodes . Call , TypeAsTBD . GetMethod ( "IsInstance" ) ) ;
}
else if ( IsGhostArray )
{
// TODO make sure we get the right "IsInstanceArray" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
2006-06-08 13:26:33 +04:00
TypeWrapper tw = this ;
int rank = 0 ;
while ( tw . IsArray )
{
rank + + ;
tw = tw . ElementTypeWrapper ;
}
ilgen . Emit ( OpCodes . Ldc_I4 , rank ) ;
ilgen . Emit ( OpCodes . Call , tw . TypeAsTBD . GetMethod ( "IsInstanceArray" ) ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2006-11-27 10:39:30 +03:00
ilgen . LazyEmit_instanceof ( TypeAsTBD ) ;
2005-06-01 13:49:30 +04:00
}
2004-01-11 16:14:42 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call MethodWrapper.Link instead
internal virtual MethodBase LinkMethod ( MethodWrapper mw )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return mw . GetMethod ( ) ;
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call FieldWrapper.Link instead
internal virtual FieldInfo LinkField ( FieldWrapper fw )
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return fw . GetField ( ) ;
2004-01-11 16:14:42 +03:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal virtual void EmitRunClassConstructor ( CodeEmitter ilgen )
2005-08-24 12:14:23 +04:00
{
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature ( ) ;
internal abstract string GetGenericMethodSignature ( MethodWrapper mw ) ;
internal abstract string GetGenericFieldSignature ( FieldWrapper fw ) ;
internal abstract string [ ] GetEnclosingMethod ( ) ;
2005-11-01 17:01:42 +03:00
internal virtual object [ ] GetDeclaredAnnotations ( )
{
return null ;
}
2006-04-19 19:49:54 +04:00
internal virtual object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
return null ;
}
internal virtual object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
return null ;
}
internal virtual object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
return null ;
}
2006-05-04 12:09:56 +04:00
internal virtual string GetSourceFileName ( )
{
return null ;
}
internal virtual int GetSourceLineNumber ( MethodBase mb , int ilOffset )
{
return - 1 ;
}
2006-04-10 13:09:09 +04:00
#if ! STATIC_COMPILER
2005-11-01 17:01:42 +03:00
internal virtual object GetAnnotationDefault ( MethodWrapper mw )
{
MethodBase mb = mw . GetMethod ( ) ;
if ( mb ! = null )
{
2007-03-13 10:44:23 +03:00
if ( mb . DeclaringType . Assembly . ReflectionOnly )
{
// TODO
return null ;
}
2005-11-01 17:01:42 +03:00
object [ ] attr = mb . GetCustomAttributes ( typeof ( AnnotationDefaultAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
2007-12-19 14:28:09 +03:00
return JVM . NewAnnotationElementValue ( mw . DeclaringType . GetClassLoader ( ) . GetJavaClassLoader ( ) , mw . ReturnType . ClassObject , ( ( AnnotationDefaultAttribute ) attr [ 0 ] ) . Value ) ;
2005-11-01 17:01:42 +03:00
}
}
return null ;
}
2007-03-13 10:44:23 +03:00
#endif // !STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
internal virtual Annotation Annotation
{
get
{
return null ;
}
}
2006-12-28 10:46:21 +03:00
internal virtual Type EnumType
{
get
{
return null ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2004-01-11 16:14:42 +03:00
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
class UnloadableTypeWrapper : TypeWrapper
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
internal UnloadableTypeWrapper ( string name )
2006-03-23 14:57:41 +03:00
: base ( TypeWrapper . UnloadableModifiersHack , name , null )
2005-06-01 13:49:30 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( name ! = "<verifier>" )
2005-06-01 13:49:30 +04:00
{
if ( name . StartsWith ( "[" ) )
{
int skip = 1 ;
while ( name [ skip + + ] = = '[' ) ;
name = name . Substring ( skip , name . Length - skip - 1 ) ;
}
2006-07-26 18:16:52 +04:00
StaticCompiler . IssueMessage ( Message . ClassNotFound , name ) ;
2005-06-01 13:49:30 +04:00
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
}
2005-02-23 15:56:15 +03:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
return null ;
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper EnsureLoadable ( ClassLoaderWrapper loader )
2005-02-23 15:56:15 +03:00
{
2005-08-25 11:46:57 +04:00
TypeWrapper tw = loader . LoadClassByDottedNameFast ( this . Name ) ;
2005-06-01 13:49:30 +04:00
if ( tw = = null )
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError ( this . Name ) ;
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
return tw ;
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
string name = Name ;
if ( name . StartsWith ( "[" ) )
{
return name ;
}
return "L" + name + ";" ;
}
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "LazyPublishMembers called on UnloadableTypeWrapper: " + Name ) ;
2005-02-23 15:56:15 +03:00
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "get_Type called on UnloadableTypeWrapper: " + Name ) ;
2006-10-04 13:03:18 +04:00
}
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "get_Interfaces called on UnloadableTypeWrapper: " + Name ) ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
{
get
{
throw new InvalidOperationException ( "get_InnerClasses called on UnloadableTypeWrapper: " + Name ) ;
}
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException ( "get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name ) ;
}
}
2003-01-06 16:56:37 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( "Finish called on UnloadableTypeWrapper: " + Name ) ;
2003-01-06 16:56:37 +03:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitCheckcast ( TypeWrapper context , CodeEmitter ilgen )
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Ldtoken , context . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldstr , Name ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . DynamicCast ) ;
2003-02-18 12:30:34 +03:00
}
2008-06-03 16:10:07 +04:00
internal override void EmitInstanceOf ( TypeWrapper context , CodeEmitter ilgen )
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Ldtoken , context . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldstr , Name ) ;
2006-04-11 16:05:24 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . DynamicInstanceOf ) ;
2003-02-18 12:30:34 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
throw new InvalidOperationException ( "GetGenericSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
throw new InvalidOperationException ( "GetGenericMethodSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
throw new InvalidOperationException ( "GetGenericFieldSignature called on UnloadableTypeWrapper: " + Name ) ;
}
internal override string [ ] GetEnclosingMethod ( )
{
throw new InvalidOperationException ( "GetEnclosingMethod called on UnloadableTypeWrapper: " + Name ) ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
class PrimitiveTypeWrapper : TypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper ( typeof ( byte ) , "B" ) ;
internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper ( typeof ( char ) , "C" ) ;
internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper ( typeof ( double ) , "D" ) ;
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper ( typeof ( float ) , "F" ) ;
internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper ( typeof ( int ) , "I" ) ;
internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper ( typeof ( long ) , "J" ) ;
internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper ( typeof ( short ) , "S" ) ;
internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper ( typeof ( bool ) , "Z" ) ;
internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper ( typeof ( void ) , "V" ) ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private readonly string sigName ;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private PrimitiveTypeWrapper ( Type type , string sigName )
2006-03-23 14:57:41 +03:00
: base ( Modifiers . Public | Modifiers . Abstract | Modifiers . Final , null , null )
2005-06-01 13:49:30 +04:00
{
this . type = type ;
this . sigName = sigName ;
}
2003-01-06 16:56:37 +03:00
2007-05-27 12:16:58 +04:00
internal static bool IsPrimitiveType ( Type type )
{
return type = = BYTE . type
| | type = = CHAR . type
| | type = = DOUBLE . type
| | type = = FLOAT . type
| | type = = INT . type
| | type = = LONG . type
| | type = = SHORT . type
| | type = = BOOLEAN . type
| | type = = VOID . type ;
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return sigName ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader ( )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetBootstrapClassLoader ( ) ;
2003-08-21 14:06:34 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
{
get
{
return type ;
}
}
2003-04-14 13:41:58 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null ;
}
2003-02-18 12:30:34 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-02-18 12:30:34 +03:00
{
}
2005-06-01 13:49:30 +04:00
public override string ToString ( )
{
return "PrimitiveTypeWrapper[" + sigName + "]" ;
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2002-12-18 19:00:25 +03:00
}
2005-02-02 18:11:26 +03:00
2008-02-10 11:45:27 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 11:13:49 +04:00
static class BakedTypeCleanupHack
2008-02-10 11:45:27 +03:00
{
private static readonly FieldInfo m_methodBuilder = typeof ( ConstructorBuilder ) . GetField ( "m_methodBuilder" , BindingFlags . Instance | BindingFlags . NonPublic ) ;
private static readonly FieldInfo [ ] methodBuilderFields = GetFieldList ( typeof ( MethodBuilder ) , new string [ ]
{
"m_ilGenerator" ,
"m_ubBody" ,
"m_RVAFixups" ,
"mm_mdMethodFixups" ,
"m_localSignature" ,
"m_localSymInfo" ,
"m_exceptions" ,
"m_parameterTypes" ,
"m_retParam" ,
"m_returnType" ,
"m_signature"
} ) ;
private static readonly FieldInfo [ ] fieldBuilderFields = GetFieldList ( typeof ( FieldBuilder ) , new string [ ]
{
"m_data" ,
"m_fieldType" ,
} ) ;
private static bool IsSupportedVersion
{
get
{
return Environment . Version . Major = = 2 & & Environment . Version . Minor = = 0 & & Environment . Version . Build = = 50727 & & Environment . Version . Revision = = 1433 ;
}
}
private static FieldInfo [ ] GetFieldList ( Type type , string [ ] list )
{
if ( JVM . SafeGetEnvironmentVariable ( "IKVM_DISABLE_TYPEBUILDER_HACK" ) ! = null | | ! IsSupportedVersion )
{
return null ;
}
if ( ! SecurityManager . IsGranted ( new SecurityPermission ( SecurityPermissionFlag . Assertion ) ) | |
! SecurityManager . IsGranted ( new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) ) )
{
return null ;
}
FieldInfo [ ] fields = new FieldInfo [ list . Length ] ;
for ( int i = 0 ; i < list . Length ; i + + )
{
fields [ i ] = type . GetField ( list [ i ] , BindingFlags . Instance | BindingFlags . NonPublic ) ;
if ( fields [ i ] = = null )
{
return null ;
}
}
return fields ;
}
internal static void Process ( DynamicTypeWrapper wrapper )
{
if ( m_methodBuilder ! = null & & methodBuilderFields ! = null & & fieldBuilderFields ! = null )
{
foreach ( MethodWrapper mw in wrapper . GetMethods ( ) )
{
MethodBuilder mb = mw . GetMethod ( ) as MethodBuilder ;
if ( mb = = null )
{
ConstructorBuilder cb = mw . GetMethod ( ) as ConstructorBuilder ;
if ( cb ! = null )
{
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
mb = ( MethodBuilder ) m_methodBuilder . GetValue ( cb ) ;
CodeAccessPermission . RevertAssert ( ) ;
}
}
if ( mb ! = null )
{
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
foreach ( FieldInfo fi in methodBuilderFields )
{
fi . SetValue ( mb , null ) ;
}
CodeAccessPermission . RevertAssert ( ) ;
}
}
foreach ( FieldWrapper fw in wrapper . GetFields ( ) )
{
FieldBuilder fb = fw . GetField ( ) as FieldBuilder ;
if ( fb ! = null )
{
new ReflectionPermission ( ReflectionPermissionFlag . MemberAccess ) . Assert ( ) ;
foreach ( FieldInfo fi in fieldBuilderFields )
{
fi . SetValue ( fb , null ) ;
}
CodeAccessPermission . RevertAssert ( ) ;
}
}
}
}
}
#endif
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
abstract class DynamicTypeWrapper : TypeWrapper
#else
2005-06-01 13:49:30 +04:00
class DynamicTypeWrapper : TypeWrapper
2006-09-12 13:57:36 +04:00
#endif
2004-08-17 13:05:21 +04:00
{
2008-08-14 11:52:27 +04:00
#if STATIC_COMPILER
protected readonly CompilerClassLoader classLoader ;
#else
2006-07-06 17:53:51 +04:00
protected readonly ClassLoaderWrapper classLoader ;
2008-08-14 11:52:27 +04:00
#endif
2005-06-01 13:49:30 +04:00
private volatile DynamicImpl impl ;
private TypeWrapper [ ] interfaces ;
2006-05-04 12:09:56 +04:00
private readonly string sourceFileName ;
2006-08-17 17:18:45 +04:00
#if ! STATIC_COMPILER
2006-05-04 12:09:56 +04:00
private byte [ ] [ ] lineNumberTables ;
2006-08-17 17:18:45 +04:00
#endif
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
private static TypeWrapper LoadTypeWrapper ( ClassLoaderWrapper classLoader , string name )
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = classLoader . LoadClassByDottedNameFast ( name ) ;
if ( tw = = null )
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError ( name ) ;
2003-06-10 17:28:47 +04:00
}
2005-06-01 13:49:30 +04:00
return tw ;
}
2008-08-14 11:52:27 +04:00
#if STATIC_COMPILER
internal DynamicTypeWrapper ( ClassFile f , CompilerClassLoader classLoader )
#else
2006-07-06 17:53:51 +04:00
internal DynamicTypeWrapper ( ClassFile f , ClassLoaderWrapper classLoader )
2008-08-14 11:52:27 +04:00
#endif
2006-03-23 14:57:41 +03:00
: base ( f . Modifiers , f . Name , f . IsInterface ? null : LoadTypeWrapper ( classLoader , f . SuperClass ) )
2005-06-01 13:49:30 +04:00
{
Profiler . Count ( "DynamicTypeWrapper" ) ;
2006-03-23 14:57:41 +03:00
this . classLoader = classLoader ;
2006-04-05 12:18:58 +04:00
this . IsInternal = f . IsInternal ;
2006-05-04 12:09:56 +04:00
this . sourceFileName = f . SourceFileAttribute ;
2005-06-01 13:49:30 +04:00
if ( BaseTypeWrapper ! = null )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! BaseTypeWrapper . IsAccessibleFrom ( this ) )
{
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its superclass " + BaseTypeWrapper . Name ) ;
}
2008-12-22 10:54:25 +03:00
#if ! STATIC_COMPILER
2008-11-14 11:42:07 +03:00
if ( ! BaseTypeWrapper . IsPublic & & ! ReflectUtil . IsFromAssembly ( BaseTypeWrapper . TypeAsBaseType , classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . Assembly ) )
2007-09-17 14:15:17 +04:00
{
// NOTE this can only happen if evil code calls ClassLoader.defineClass() on an assembly class loader (which we allow for compatibility with other slightly less evil code)
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its non-public superclass " + BaseTypeWrapper . Name + " from another assembly" ) ;
}
2008-12-22 10:54:25 +03:00
#endif
2005-06-01 13:49:30 +04:00
if ( BaseTypeWrapper . IsFinal )
{
2005-07-27 19:57:55 +04:00
throw new VerifyError ( "Class " + f . Name + " extends final class " + BaseTypeWrapper . Name ) ;
2005-06-01 13:49:30 +04:00
}
if ( BaseTypeWrapper . IsInterface )
{
throw new IncompatibleClassChangeError ( "Class " + f . Name + " has interface " + BaseTypeWrapper . Name + " as superclass" ) ;
}
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( Delegate ) )
{
throw new VerifyError ( BaseTypeWrapper . Name + " cannot be used as a base class" ) ;
}
2009-03-06 08:33:08 +03:00
// NOTE defining value types, enums is not supported in IKVM v1
2004-10-04 23:30:53 +04:00
if ( BaseTypeWrapper . TypeAsTBD = = typeof ( ValueType ) | | BaseTypeWrapper . TypeAsTBD = = typeof ( Enum ) )
{
2005-06-01 13:49:30 +04:00
throw new VerifyError ( "Defining value types in Java is not implemented in IKVM v1" ) ;
2004-10-04 23:30:53 +04:00
}
2009-03-06 08:33:08 +03:00
if ( IsDelegate )
2004-10-04 23:30:53 +04:00
{
2009-03-06 08:33:08 +03:00
VerifyDelegate ( f ) ;
2004-10-04 23:30:53 +04:00
}
}
2005-06-01 13:49:30 +04:00
ClassFile . ConstantPoolItemClass [ ] interfaces = f . Interfaces ;
this . interfaces = new TypeWrapper [ interfaces . Length ] ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper iface = LoadTypeWrapper ( classLoader , interfaces [ i ] . Name ) ;
if ( ! iface . IsAccessibleFrom ( this ) )
{
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its superinterface " + iface . Name ) ;
}
2008-12-22 10:54:25 +03:00
#if ! STATIC_COMPILER
2007-09-17 14:15:17 +04:00
if ( ! iface . IsPublic
2008-11-14 11:42:07 +03:00
& & ! ReflectUtil . IsFromAssembly ( iface . TypeAsBaseType , classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . Assembly )
& & ReflectUtil . GetAssembly ( iface . TypeAsBaseType ) . GetType ( DynamicClassLoader . GetProxyHelperName ( iface . TypeAsTBD ) ) = = null )
2007-09-17 14:15:17 +04:00
{
// NOTE this happens when you call Proxy.newProxyInstance() on a non-public .NET interface
// (for ikvmc compiled Java types, ikvmc generates public proxy stubs).
// NOTE we don't currently check interfaces inherited from other interfaces because mainstream .NET languages
// don't allow public interfaces extending non-public interfaces.
throw new IllegalAccessError ( "Class " + f . Name + " cannot access its non-public superinterface " + iface . Name + " from another assembly" ) ;
}
2008-12-22 10:54:25 +03:00
#endif
2005-06-01 13:49:30 +04:00
if ( ! iface . IsInterface )
{
throw new IncompatibleClassChangeError ( "Implementing class" ) ;
}
this . interfaces [ i ] = iface ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
impl = new JavaTypeImpl ( f , this ) ;
2003-01-06 16:56:37 +03:00
}
2004-08-17 13:05:21 +04:00
2009-03-06 08:33:08 +03:00
private void VerifyDelegate ( ClassFile f )
{
if ( ! f . IsFinal )
{
throw new VerifyError ( "Delegate must be final" ) ;
}
ClassFile . Method invoke = null ;
ClassFile . Method beginInvoke = null ;
ClassFile . Method endInvoke = null ;
ClassFile . Method constructor = null ;
foreach ( ClassFile . Method m in f . Methods )
{
if ( m . Name = = "Invoke" )
{
if ( invoke ! = null )
{
throw new VerifyError ( "Delegate may only have a single Invoke method" ) ;
}
invoke = m ;
}
else if ( m . Name = = "BeginInvoke" )
{
if ( beginInvoke ! = null )
{
throw new VerifyError ( "Delegate may only have a single BeginInvoke method" ) ;
}
beginInvoke = m ;
}
else if ( m . Name = = "EndInvoke" )
{
if ( endInvoke ! = null )
{
throw new VerifyError ( "Delegate may only have a single EndInvoke method" ) ;
}
endInvoke = m ;
}
else if ( m . Name = = "<init>" )
{
if ( constructor ! = null )
{
throw new VerifyError ( "Delegate may only have a single constructor" ) ;
}
constructor = m ;
}
else if ( m . IsNative )
{
throw new VerifyError ( "Delegate may not have any native methods besides Invoke, BeginInvoke and EndInvoke" ) ;
}
}
if ( invoke = = null | | constructor = = null )
{
throw new VerifyError ( "Delegate must have a constructor and an Invoke method" ) ;
}
if ( ! invoke . IsPublic | | ! invoke . IsNative | | invoke . IsFinal | | invoke . IsStatic )
{
throw new VerifyError ( "Delegate Invoke method must be a public native non-final instance method" ) ;
}
if ( ( beginInvoke ! = null & & endInvoke = = null ) | | ( beginInvoke = = null & & endInvoke ! = null ) )
{
throw new VerifyError ( "Delegate must have both BeginInvoke and EndInvoke or neither" ) ;
}
2009-03-06 09:43:40 +03:00
if ( ! constructor . IsPublic )
{
throw new VerifyError ( "Delegate constructor must be public" ) ;
}
2009-03-06 08:33:08 +03:00
if ( constructor . Instructions . Length < 3
| | constructor . Instructions [ 0 ] . NormalizedOpCode ! = NormalizedByteCode . __aload
| | constructor . Instructions [ 0 ] . NormalizedArg1 ! = 0
| | constructor . Instructions [ 1 ] . NormalizedOpCode ! = NormalizedByteCode . __invokespecial
| | constructor . Instructions [ 2 ] . NormalizedOpCode ! = NormalizedByteCode . __return )
{
throw new VerifyError ( "Delegate constructor must be empty" ) ;
}
if ( f . Fields . Length ! = 0 )
{
throw new VerifyError ( "Delegate may not declare any fields" ) ;
}
2009-03-07 11:33:33 +03:00
TypeWrapper iface ;
#if STATIC_COMPILER
iface = classLoader . LoadCircularDependencyHack ( this , f . Name + DotNetTypeWrapper . DelegateInterfaceSuffix ) ;
#else
iface = classLoader . LoadClassByDottedNameFast ( f . Name + DotNetTypeWrapper . DelegateInterfaceSuffix ) ;
#endif
2009-03-06 08:33:08 +03:00
DelegateInnerClassCheck ( iface ! = null ) ;
DelegateInnerClassCheck ( iface . IsInterface ) ;
DelegateInnerClassCheck ( iface . IsPublic ) ;
DelegateInnerClassCheck ( iface . GetClassLoader ( ) = = classLoader ) ;
MethodWrapper [ ] methods = iface . GetMethods ( ) ;
DelegateInnerClassCheck ( methods . Length = = 1 & & methods [ 0 ] . Name = = "Invoke" ) ;
if ( methods [ 0 ] . Signature ! = invoke . Signature )
{
throw new VerifyError ( "Delegate Invoke method signature must be identical to inner interface Invoke method signature" ) ;
}
if ( iface . Interfaces . Length ! = 0 )
{
throw new VerifyError ( "Delegate inner interface may not extend any interfaces" ) ;
}
if ( constructor . Signature ! = "(" + iface . SigName + ")V" )
{
throw new VerifyError ( "Delegate constructor must take a single argument of type inner Method interface" ) ;
}
2009-03-07 11:33:33 +03:00
if ( beginInvoke ! = null & & beginInvoke . Signature ! = invoke . Signature . Substring ( 0 , invoke . Signature . IndexOf ( ')' ) ) + "Lcli.System.AsyncCallback;Ljava.lang.Object;)Lcli.System.IAsyncResult;" )
2009-03-06 08:33:08 +03:00
{
throw new VerifyError ( "Delegate BeginInvoke method has incorrect signature" ) ;
}
2009-03-07 11:33:33 +03:00
if ( endInvoke ! = null & & endInvoke . Signature ! = "(Lcli.System.IAsyncResult;)" + invoke . Signature . Substring ( invoke . Signature . IndexOf ( ')' ) + 1 ) )
2009-03-06 08:33:08 +03:00
{
throw new VerifyError ( "Delegate EndInvoke method has incorrect signature" ) ;
}
}
private static void DelegateInnerClassCheck ( bool cond )
{
if ( ! cond )
{
throw new VerifyError ( "Delegate must have a public inner interface named Method with a single method named Invoke" ) ;
}
}
private bool IsDelegate
{
get
{
TypeWrapper baseTypeWrapper = BaseTypeWrapper ;
return baseTypeWrapper ! = null & & baseTypeWrapper . TypeAsTBD = = typeof ( MulticastDelegate ) ;
}
}
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
return classLoader ;
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . ReflectiveModifiers ;
}
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return interfaces ;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . InnerClasses ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . DeclaringTypeWrapper ;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl . Type ;
}
2002-12-18 19:00:25 +03:00
}
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
internal override Annotation Annotation
{
get
{
return impl . Annotation ;
}
}
internal override Type EnumType
{
get
{
return impl . EnumType ;
}
}
#endif // STATIC_COMPILER
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-01-02 16:46:16 +03:00
{
2006-05-05 15:21:15 +04:00
// we don't need locking, because Finish is Thread safe
impl = impl . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
// NOTE can only be used if the type hasn't been finished yet!
protected string GenerateUniqueMethodName ( string basename , MethodWrapper mw )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return ( ( JavaTypeImpl ) impl ) . GenerateUniqueMethodName ( basename , mw ) ;
2004-03-08 18:18:47 +03:00
}
2004-09-17 13:32:06 +04:00
2007-07-31 19:27:22 +04:00
// NOTE can only be used if the type hasn't been finished yet!
internal string GenerateUniqueMethodName ( string basename , Type returnType , Type [ ] parameterTypes )
{
return ( ( JavaTypeImpl ) impl ) . GenerateUniqueMethodName ( basename , returnType , parameterTypes ) ;
}
2006-05-05 15:21:15 +04:00
internal void CreateStep1 ( out bool hasclinit )
{
( ( JavaTypeImpl ) impl ) . CreateStep1 ( out hasclinit ) ;
}
internal void CreateStep2NoFail ( bool hasclinit , string mangledTypeName )
{
( ( JavaTypeImpl ) impl ) . CreateStep2NoFail ( hasclinit , mangledTypeName ) ;
}
2005-06-01 13:49:30 +04:00
private abstract class DynamicImpl
{
internal abstract Type Type { get ; }
internal abstract TypeWrapper [ ] InnerClasses { get ; }
internal abstract TypeWrapper DeclaringTypeWrapper { get ; }
internal abstract Modifiers ReflectiveModifiers { get ; }
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
internal abstract Annotation Annotation { get ; }
internal abstract Type EnumType { get ; }
#endif
2005-08-05 12:40:54 +04:00
internal abstract DynamicImpl Finish ( ) ;
2005-06-01 13:49:30 +04:00
internal abstract MethodBase LinkMethod ( MethodWrapper mw ) ;
internal abstract FieldInfo LinkField ( FieldWrapper fw ) ;
2008-06-03 16:10:07 +04:00
internal abstract void EmitRunClassConstructor ( CodeEmitter ilgen ) ;
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature ( ) ;
internal abstract string [ ] GetEnclosingMethod ( ) ;
internal abstract string GetGenericMethodSignature ( int index ) ;
internal abstract string GetGenericFieldSignature ( int index ) ;
2005-11-01 17:01:42 +03:00
internal abstract object [ ] GetDeclaredAnnotations ( ) ;
internal abstract object GetMethodDefaultValue ( int index ) ;
2006-04-19 19:49:54 +04:00
internal abstract object [ ] GetMethodAnnotations ( int index ) ;
internal abstract object [ ] [ ] GetParameterAnnotations ( int index ) ;
internal abstract object [ ] GetFieldAnnotations ( int index ) ;
2008-11-14 11:37:22 +03:00
internal abstract MethodInfo GetFinalizeMethod ( ) ;
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
2006-05-15 13:08:01 +04:00
private sealed class JavaTypeImpl : DynamicImpl
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly ClassFile classFile ;
private readonly DynamicTypeWrapper wrapper ;
2006-05-05 15:21:15 +04:00
private TypeBuilder typeBuilder ;
2005-06-01 13:49:30 +04:00
private MethodWrapper [ ] methods ;
private MethodWrapper [ ] baseMethods ;
private FieldWrapper [ ] fields ;
private FinishedTypeImpl finishedType ;
2008-02-29 10:08:04 +03:00
private bool finishInProgress ;
2008-08-15 16:01:06 +04:00
private Dictionary < string , string > memberclashtable ;
2005-08-24 12:14:23 +04:00
private MethodBuilder clinitMethod ;
2007-09-07 16:37:03 +04:00
private MethodBuilder finalizeMethod ;
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2006-05-15 13:08:01 +04:00
private DynamicTypeWrapper outerClassWrapper ;
2005-11-01 17:01:42 +03:00
private AnnotationBuilder annotationBuilder ;
2006-12-28 10:46:21 +03:00
private TypeBuilder enumBuilder ;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal JavaTypeImpl ( ClassFile f , DynamicTypeWrapper wrapper )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Tracer . Info ( Tracer . Compiler , "constructing JavaTypeImpl for " + f . Name ) ;
this . classFile = f ;
this . wrapper = wrapper ;
2006-05-05 15:21:15 +04:00
}
2005-06-01 13:49:30 +04:00
2006-05-05 15:21:15 +04:00
internal void CreateStep1 ( out bool hasclinit )
{
2005-06-01 13:49:30 +04:00
// process all methods
2006-05-05 15:21:15 +04:00
hasclinit = wrapper . BaseTypeWrapper = = null ? false : wrapper . BaseTypeWrapper . HasStaticInitializer ;
2005-06-01 13:49:30 +04:00
methods = new MethodWrapper [ classFile . Methods . Length ] ;
baseMethods = new MethodWrapper [ classFile . Methods . Length ] ;
for ( int i = 0 ; i < methods . Length ; i + + )
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Method m = classFile . Methods [ i ] ;
if ( m . IsClassInitializer )
2004-09-15 17:35:44 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if ( ! IsSideEffectFreeStaticInitializer ( m ) )
2004-09-15 17:35:44 +04:00
{
hasclinit = true ;
}
2006-04-10 13:09:09 +04:00
#else
hasclinit = true ;
#endif
2004-09-15 17:35:44 +04:00
}
2006-04-05 12:18:58 +04:00
MemberFlags flags = MemberFlags . None ;
if ( m . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
2008-05-31 19:20:29 +04:00
// we only support HasCallerID instance methods on final types, because we don't support interface stubs with CallerID
2008-06-02 10:20:29 +04:00
if ( m . HasCallerIDAnnotation
& & ( m . IsStatic | | classFile . IsFinal )
2009-02-10 10:24:30 +03:00
& & CoreClasses . java . lang . Object . Wrapper . InternalsVisibleTo ( wrapper ) )
2008-05-31 19:20:29 +04:00
{
flags | = MemberFlags . CallerID ;
}
2005-06-01 13:49:30 +04:00
if ( wrapper . IsGhost )
{
2006-04-05 12:18:58 +04:00
methods [ i ] = new MethodWrapper . GhostMethodWrapper ( wrapper , m . Name , m . Signature , null , null , null , m . Modifiers , flags ) ;
2005-06-01 13:49:30 +04:00
}
2009-03-06 08:33:08 +03:00
else if ( ReferenceEquals ( m . Name , StringConstants . INIT ) & & wrapper . IsDelegate )
{
methods [ i ] = new DelegateConstructorMethodWrapper ( wrapper , m ) ;
}
2007-12-27 18:08:05 +03:00
else if ( ReferenceEquals ( m . Name , StringConstants . INIT ) | | m . IsClassInitializer )
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
methods [ i ] = new SmartConstructorMethodWrapper ( wrapper , m . Name , m . Signature , null , null , m . Modifiers , flags ) ;
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
else
{
2005-06-01 13:49:30 +04:00
if ( ! classFile . IsInterface & & ! m . IsStatic & & ! m . IsPrivate )
{
2006-04-05 12:18:58 +04:00
bool explicitOverride = false ;
2005-06-01 13:49:30 +04:00
baseMethods [ i ] = FindBaseMethod ( m . Name , m . Signature , out explicitOverride ) ;
2006-04-05 12:18:58 +04:00
if ( explicitOverride )
{
flags | = MemberFlags . ExplicitOverride ;
}
2005-06-01 13:49:30 +04:00
}
2006-04-05 12:18:58 +04:00
methods [ i ] = new SmartCallMethodWrapper ( wrapper , m . Name , m . Signature , null , null , null , m . Modifiers , flags , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
2004-09-15 17:35:44 +04:00
}
}
2006-04-05 12:18:58 +04:00
wrapper . HasStaticInitializer = hasclinit ;
2007-08-03 17:14:41 +04:00
if ( ! wrapper . IsInterface | | wrapper . IsPublic )
2003-02-20 17:18:38 +03:00
{
2008-08-15 16:01:06 +04:00
List < MethodWrapper > methodsArray = null ;
List < MethodWrapper > baseMethodsArray = null ;
2005-08-14 19:49:50 +04:00
if ( wrapper . IsAbstract )
{
2008-08-15 16:01:06 +04:00
methodsArray = new List < MethodWrapper > ( methods ) ;
baseMethodsArray = new List < MethodWrapper > ( baseMethods ) ;
2005-08-14 19:49:50 +04:00
AddMirandaMethods ( methodsArray , baseMethodsArray , wrapper ) ;
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2007-08-03 17:14:41 +04:00
if ( ! wrapper . IsInterface & & wrapper . IsPublic )
2005-08-14 19:49:50 +04:00
{
TypeWrapper baseTypeWrapper = wrapper . BaseTypeWrapper ;
while ( baseTypeWrapper ! = null & & ! baseTypeWrapper . IsPublic )
{
if ( methodsArray = = null )
{
2008-08-15 16:01:06 +04:00
methodsArray = new List < MethodWrapper > ( methods ) ;
baseMethodsArray = new List < MethodWrapper > ( baseMethods ) ;
2005-08-14 19:49:50 +04:00
}
AddAccessStubMethods ( methodsArray , baseMethodsArray , baseTypeWrapper ) ;
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
}
}
2006-04-10 13:09:09 +04:00
#endif
2005-08-14 19:49:50 +04:00
if ( methodsArray ! = null )
{
2008-08-15 16:01:06 +04:00
this . methods = methodsArray . ToArray ( ) ;
this . baseMethods = baseMethodsArray . ToArray ( ) ;
2005-08-14 19:49:50 +04:00
}
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
wrapper . SetMethods ( methods ) ;
fields = new FieldWrapper [ classFile . Fields . Length ] ;
for ( int i = 0 ; i < fields . Length ; i + + )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
ClassFile . Field fld = classFile . Fields [ i ] ;
if ( fld . IsStatic & & fld . IsFinal & & fld . ConstantValue ! = null )
2004-08-17 13:05:21 +04:00
{
2006-10-10 20:24:48 +04:00
TypeWrapper fieldType = null ;
#if ! STATIC_COMPILER
fieldType = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . FieldTypeWrapperFromSig ( fld . Signature ) ;
#endif
fields [ i ] = new ConstantFieldWrapper ( wrapper , fieldType , fld . Name , fld . Signature , fld . Modifiers , null , fld . ConstantValue , MemberFlags . None ) ;
2005-06-01 13:49:30 +04:00
}
2008-04-14 09:13:41 +04:00
else if ( fld . IsProperty )
{
fields [ i ] = new DynamicPropertyFieldWrapper ( wrapper , fld ) ;
}
2005-06-01 13:49:30 +04:00
else
{
2006-04-05 12:18:58 +04:00
fields [ i ] = FieldWrapper . Create ( wrapper , null , null , fld . Name , fld . Signature , new ExModifiers ( fld . Modifiers , fld . IsInternal ) ) ;
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2007-08-03 17:14:41 +04:00
if ( wrapper . IsPublic )
2005-08-14 19:49:50 +04:00
{
2008-08-15 16:01:06 +04:00
List < FieldWrapper > fieldsArray = new List < FieldWrapper > ( fields ) ;
2005-08-14 19:49:50 +04:00
AddAccessStubFields ( fieldsArray , wrapper ) ;
2008-08-15 16:01:06 +04:00
fields = fieldsArray . ToArray ( ) ;
2005-08-14 19:49:50 +04:00
}
2007-06-28 14:32:50 +04:00
( ( AotTypeWrapper ) wrapper ) . AddMapXmlFields ( ref fields ) ;
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
wrapper . SetFields ( fields ) ;
2006-05-05 15:21:15 +04:00
}
2004-08-17 13:05:21 +04:00
2006-05-05 15:21:15 +04:00
internal void CreateStep2NoFail ( bool hasclinit , string mangledTypeName )
{
2006-05-15 13:08:01 +04:00
// this method is not allowed to throw exceptions (if it does, the runtime will abort)
2006-05-05 15:21:15 +04:00
ClassFile f = classFile ;
2005-06-01 13:49:30 +04:00
try
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeAttributes typeAttribs = 0 ;
if ( f . IsAbstract )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Abstract ;
}
if ( f . IsFinal )
{
typeAttribs | = TypeAttributes . Sealed ;
}
if ( ! hasclinit )
{
typeAttribs | = TypeAttributes . BeforeFieldInit ;
}
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2007-10-10 09:31:57 +04:00
bool cantNest = false ;
2006-10-09 16:32:33 +04:00
bool setModifiers = false ;
2005-06-01 13:49:30 +04:00
TypeBuilder outer = null ;
2006-05-15 13:08:01 +04:00
// we only compile inner classes as nested types in the static compiler, because it has a higher cost
// and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling
// the TypeResolve event very hard)
ClassFile . InnerClass outerClass = getOuterClass ( ) ;
if ( outerClass . outerClass ! = 0 )
2005-06-01 13:49:30 +04:00
{
2006-05-15 13:08:01 +04:00
string outerClassName = classFile . GetConstantPoolClass ( outerClass . outerClass ) ;
if ( ! CheckInnerOuterNames ( f . Name , outerClassName ) )
2004-08-17 13:05:21 +04:00
{
2006-05-15 13:08:01 +04:00
Tracer . Warning ( Tracer . Compiler , "Incorrect InnerClasses attribute on {0}" , f . Name ) ;
}
else
{
try
2005-06-01 13:49:30 +04:00
{
2009-03-07 11:33:33 +03:00
outerClassWrapper = wrapper . GetClassLoader ( ) . LoadCircularDependencyHack ( wrapper , outerClassName ) as DynamicTypeWrapper ;
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
catch ( RetargetableJavaException x )
2004-08-17 13:05:21 +04:00
{
2006-10-27 20:55:07 +04:00
Tracer . Warning ( Tracer . Compiler , "Unable to load outer class {0} for inner class {1} ({2}: {3})" , outerClassName , f . Name , x . GetType ( ) . Name , x . Message ) ;
2006-05-15 13:08:01 +04:00
}
if ( outerClassWrapper ! = null )
{
// make sure the relationship is reciprocal (otherwise we run the risk of
2008-08-14 09:40:40 +04:00
// baking the outer type before the inner type) and that the inner and outer
// class live in the same class loader (when doing a multi target compilation,
// it is possible to split the two classes acros assemblies)
if ( outerClassWrapper . impl is JavaTypeImpl & & outerClassWrapper . GetClassLoader ( ) = = wrapper . GetClassLoader ( ) )
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
ClassFile outerClassFile = ( ( JavaTypeImpl ) outerClassWrapper . impl ) . classFile ;
ClassFile . InnerClass [ ] outerInnerClasses = outerClassFile . InnerClasses ;
if ( outerInnerClasses = = null )
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
outerClassWrapper = null ;
}
else
{
bool ok = false ;
for ( int i = 0 ; i < outerInnerClasses . Length ; i + + )
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
if ( outerInnerClasses [ i ] . outerClass ! = 0
& & outerClassFile . GetConstantPoolClass ( outerInnerClasses [ i ] . outerClass ) = = outerClassFile . Name
& & outerInnerClasses [ i ] . innerClass ! = 0
& & outerClassFile . GetConstantPoolClass ( outerInnerClasses [ i ] . innerClass ) = = f . Name )
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
ok = true ;
break ;
2005-08-03 16:59:16 +04:00
}
}
2006-05-15 13:08:01 +04:00
if ( ! ok )
2005-08-03 16:59:16 +04:00
{
outerClassWrapper = null ;
}
}
2006-05-15 13:08:01 +04:00
}
else
{
outerClassWrapper = null ;
}
if ( outerClassWrapper ! = null )
{
outer = outerClassWrapper . TypeAsBuilder ;
}
else
{
Tracer . Warning ( Tracer . Compiler , "Non-reciprocal inner class {0}" , f . Name ) ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
}
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
if ( f . IsPublic )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if ( outer ! = null )
{
2007-10-10 09:31:57 +04:00
if ( outerClassWrapper . IsPublic )
{
typeAttribs | = TypeAttributes . NestedPublic ;
}
else
{
// We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type,
// because that would mean it wouldn't be visible outside the assembly.
cantNest = true ;
typeAttribs | = TypeAttributes . Public ;
}
2005-06-01 13:49:30 +04:00
}
else
{
typeAttribs | = TypeAttributes . Public ;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( outer ! = null )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . NestedAssembly ;
2003-10-17 12:08:31 +04:00
}
2006-05-15 13:08:01 +04:00
#else // STATIC_COMPILER
if ( f . IsPublic )
{
typeAttribs | = TypeAttributes . Public ;
}
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if ( f . IsInterface )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Interface | TypeAttributes . Abstract ;
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2007-10-10 09:31:57 +04:00
if ( outer ! = null & & ! cantNest )
2005-06-01 13:49:30 +04:00
{
if ( wrapper . IsGhost )
{
// TODO this is low priority, since the current Java class library doesn't define any ghost interfaces
// as inner classes
throw new NotImplementedException ( ) ;
}
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer . DefineNestedType ( GetInnerClassName ( outerClassWrapper . Name , f . Name ) , typeAttribs ) ;
}
else
2004-08-17 13:05:21 +04:00
{
2006-09-12 13:57:36 +04:00
if ( wrapper . IsGhost )
{
typeBuilder = wrapper . DefineGhostType ( mangledTypeName , typeAttribs ) ;
}
else
{
typeBuilder = wrapper . classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . DefineType ( mangledTypeName , typeAttribs ) ;
}
2004-08-17 13:05:21 +04:00
}
2006-09-12 13:57:36 +04:00
#else // STATIC_COMPILER
typeBuilder = wrapper . classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . DefineType ( mangledTypeName , typeAttribs ) ;
#endif // STATIC_COMPILER
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
typeAttribs | = TypeAttributes . Class ;
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2006-10-09 16:32:33 +04:00
if ( f . IsEffectivelyFinal )
{
if ( outer = = null )
{
setModifiers = true ;
}
else
{
// we don't need a ModifiersAttribute, because the InnerClassAttribute already records
// the modifiers
}
typeAttribs | = TypeAttributes . Sealed ;
Tracer . Info ( Tracer . Compiler , "Sealing type {0}" , f . Name ) ;
}
2007-10-10 09:31:57 +04:00
if ( outer ! = null & & ! cantNest )
2005-06-01 13:49:30 +04:00
{
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer . DefineNestedType ( GetInnerClassName ( outerClassWrapper . Name , f . Name ) , typeAttribs , wrapper . BaseTypeWrapper . TypeAsBaseType ) ;
}
else
2006-05-15 13:08:01 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
{
2006-07-26 18:16:52 +04:00
typeBuilder = wrapper . classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . DefineType ( mangledTypeName , typeAttribs , wrapper . BaseTypeWrapper . TypeAsBaseType ) ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2006-07-24 12:21:11 +04:00
#if STATIC_COMPILER
2007-10-10 09:31:57 +04:00
if ( outer ! = null & & cantNest )
{
AttributeHelper . SetNonNestedOuterClass ( typeBuilder , outerClassWrapper . Name ) ;
AttributeHelper . SetNonNestedInnerClass ( outer , f . Name ) ;
}
2006-07-24 12:21:11 +04:00
if ( outer = = null & & mangledTypeName ! = wrapper . Name )
{
// HACK we abuse the InnerClassAttribute to record to real name
AttributeHelper . SetInnerClass ( typeBuilder , wrapper . Name , wrapper . Modifiers ) ;
2006-08-14 11:57:03 +04:00
}
if ( typeBuilder . FullName ! = wrapper . Name
& & wrapper . Name . Replace ( '$' , '+' ) ! = typeBuilder . FullName )
{
( ( CompilerClassLoader ) wrapper . GetClassLoader ( ) ) . AddNameMapping ( wrapper . Name , typeBuilder . FullName ) ;
2006-07-24 12:21:11 +04:00
}
2006-05-15 13:08:01 +04:00
if ( f . IsAnnotation & & Annotation . HasRetentionPolicyRuntime ( f . Annotations ) )
{
annotationBuilder = new AnnotationBuilder ( this ) ;
( ( AotTypeWrapper ) wrapper ) . SetAnnotation ( annotationBuilder ) ;
}
2006-12-28 10:46:21 +03:00
// For Java 5 Enum types, we generate a nested .NET enum.
// This is primarily to support annotations that take enum parameters.
if ( f . IsEnum & & f . IsPublic )
{
// TODO make sure there isn't already a nested type with the __Enum name
enumBuilder = wrapper . TypeAsBuilder . DefineNestedType ( "__Enum" , TypeAttributes . Class | TypeAttributes . Sealed | TypeAttributes . NestedPublic | TypeAttributes . Serializable , typeof ( Enum ) ) ;
AttributeHelper . HideFromJava ( enumBuilder ) ;
enumBuilder . DefineField ( "value__" , typeof ( int ) , FieldAttributes . Public | FieldAttributes . SpecialName | FieldAttributes . RTSpecialName ) ;
for ( int i = 0 ; i < f . Fields . Length ; i + + )
{
if ( f . Fields [ i ] . IsEnum )
{
FieldBuilder fieldBuilder = enumBuilder . DefineField ( f . Fields [ i ] . Name , enumBuilder , FieldAttributes . Public | FieldAttributes . Static | FieldAttributes . Literal ) ;
fieldBuilder . SetConstant ( i ) ;
}
}
}
2007-03-07 18:41:18 +03:00
TypeWrapper [ ] interfaces = wrapper . Interfaces ;
2006-05-15 13:08:01 +04:00
string [ ] implements = new string [ interfaces . Length ] ;
for ( int i = 0 ; i < implements . Length ; i + + )
{
implements [ i ] = interfaces [ i ] . Name ;
}
2006-08-17 17:18:45 +04:00
if ( outer ! = null )
2006-05-15 13:08:01 +04:00
{
2006-08-17 17:18:45 +04:00
Modifiers innerClassModifiers = outerClass . accessFlags ;
string innerClassName = classFile . GetConstantPoolClass ( outerClass . innerClass ) ;
if ( innerClassName = = classFile . Name & & innerClassName = = outerClassWrapper . Name + "$" + typeBuilder . Name )
2006-05-15 13:08:01 +04:00
{
2006-08-17 17:18:45 +04:00
innerClassName = null ;
2006-05-15 13:08:01 +04:00
}
2006-08-17 17:18:45 +04:00
AttributeHelper . SetInnerClass ( typeBuilder , innerClassName , innerClassModifiers ) ;
2006-05-15 13:08:01 +04:00
}
2006-08-17 17:18:45 +04:00
else if ( outerClass . innerClass ! = 0 )
{
AttributeHelper . SetInnerClass ( typeBuilder , null , outerClass . accessFlags ) ;
}
2005-06-01 13:49:30 +04:00
AttributeHelper . SetImplementsAttribute ( typeBuilder , interfaces ) ;
2006-05-04 12:09:56 +04:00
if ( classFile . DeprecatedAttribute )
2004-08-17 13:05:21 +04:00
{
2006-05-04 12:09:56 +04:00
AttributeHelper . SetDeprecatedAttribute ( typeBuilder ) ;
}
if ( classFile . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( typeBuilder , classFile . GenericSignature ) ;
}
if ( classFile . EnclosingMethod ! = null )
{
AttributeHelper . SetEnclosingMethodAttribute ( typeBuilder , classFile . EnclosingMethod [ 0 ] , classFile . EnclosingMethod [ 1 ] , classFile . EnclosingMethod [ 2 ] ) ;
2005-06-01 13:49:30 +04:00
}
2006-08-29 10:28:34 +04:00
if ( wrapper . classLoader . EmitStackTraceInfo )
2005-06-01 13:49:30 +04:00
{
2005-07-07 15:24:08 +04:00
if ( f . SourceFileAttribute ! = null )
{
if ( f . SourceFileAttribute ! = typeBuilder . Name + ".java" )
{
AttributeHelper . SetSourceFile ( typeBuilder , f . SourceFileAttribute ) ;
}
}
else
{
AttributeHelper . SetSourceFile ( typeBuilder , null ) ;
}
2004-08-17 13:05:21 +04:00
}
2006-05-15 13:08:01 +04:00
// NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types
2006-10-09 16:32:33 +04:00
if ( setModifiers | | classFile . IsInternal | | ( classFile . Modifiers & ( Modifiers . Synthetic | Modifiers . Annotation | Modifiers . Enum ) ) ! = 0 )
2006-05-15 13:08:01 +04:00
{
AttributeHelper . SetModifiers ( typeBuilder , classFile . Modifiers , classFile . IsInternal ) ;
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2007-11-26 14:01:29 +03:00
if ( hasclinit )
2005-08-24 12:14:23 +04:00
{
// We create a empty method that we can use to trigger our .cctor
// (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges)
MethodAttributes attribs = MethodAttributes . Static | MethodAttributes . SpecialName ;
if ( classFile . IsAbstract )
{
bool hasfields = false ;
// If we have any public static fields, the cctor trigger must (and may) be public as well
foreach ( ClassFile . Field fld in classFile . Fields )
{
if ( fld . IsPublic & & fld . IsStatic )
{
hasfields = true ;
break ;
}
}
attribs | = hasfields ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
}
else
{
attribs | = MethodAttributes . Public ;
}
clinitMethod = typeBuilder . DefineMethod ( "__<clinit>" , attribs , null , null ) ;
clinitMethod . GetILGenerator ( ) . Emit ( OpCodes . Ret ) ;
2007-10-12 12:52:08 +04:00
// FXBUG on .NET 2.0 RTM x64 the JIT sometimes throws an InvalidProgramException while trying to inline this method,
// so we prevent inlining for now (it also turns out that on x86 not inlining this method actually has a positive perf impact in some cases...)
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=285772
clinitMethod . SetImplementationFlags ( clinitMethod . GetMethodImplementationFlags ( ) | MethodImplAttributes . NoInlining ) ;
2005-08-24 12:14:23 +04:00
}
2007-08-21 11:22:05 +04:00
if ( HasStructLayoutAttributeAnnotation ( classFile ) )
{
// when we have a StructLayoutAttribute, field order is significant,
// so we link all fields here to make sure they are created in class file order.
foreach ( FieldWrapper fw in fields )
{
fw . Link ( ) ;
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
catch ( Exception x )
2004-10-19 17:43:55 +04:00
{
2006-05-05 15:21:15 +04:00
JVM . CriticalFailure ( "Exception during JavaTypeImpl.CreateStep2NoFail" , x ) ;
2004-10-19 17:43:55 +04:00
}
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
2009-03-06 08:33:08 +03:00
private sealed class DelegateConstructorMethodWrapper : MethodWrapper
{
2009-03-06 09:43:40 +03:00
private ConstructorBuilder constructor ;
private MethodInfo invoke ;
2009-03-06 08:33:08 +03:00
internal DelegateConstructorMethodWrapper ( DynamicTypeWrapper tw , ClassFile . Method m )
: base ( tw , m . Name , m . Signature , null , null , null , m . Modifiers , MemberFlags . None )
{
}
2009-03-06 09:43:40 +03:00
protected override void DoLinkMethod ( )
2009-03-06 08:33:08 +03:00
{
2009-03-06 09:43:40 +03:00
MethodAttributes attribs = MethodAttributes . HideBySig | MethodAttributes . Public ;
constructor = this . DeclaringType . TypeAsBuilder . DefineConstructor ( attribs , CallingConventions . Standard , new Type [ ] { typeof ( object ) , typeof ( IntPtr ) } , null , null ) ;
constructor . SetImplementationFlags ( MethodImplAttributes . Runtime ) ;
2009-03-06 08:33:08 +03:00
MethodWrapper mw = GetParameters ( ) [ 0 ] . GetMethods ( ) [ 0 ] ;
mw . Link ( ) ;
2009-03-06 09:43:40 +03:00
invoke = ( MethodInfo ) mw . GetMethod ( ) ;
}
internal override void EmitNewobj ( CodeEmitter ilgen , MethodAnalyzer ma , int opcodeIndex )
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Ldvirtftn , invoke ) ;
ilgen . Emit ( OpCodes . Newobj , constructor ) ;
2009-03-06 08:33:08 +03:00
}
}
2007-08-21 11:22:05 +04:00
private static bool HasStructLayoutAttributeAnnotation ( ClassFile c )
{
if ( c . Annotations ! = null )
{
foreach ( object [ ] annot in c . Annotations )
{
if ( "Lcli/System/Runtime/InteropServices/StructLayoutAttribute$Annotation;" . Equals ( annot [ 1 ] ) )
{
return true ;
}
}
}
return false ;
}
2008-05-20 11:43:42 +04:00
#if STATIC_COMPILER
2006-05-15 13:08:01 +04:00
private ClassFile . InnerClass getOuterClass ( )
2005-08-03 16:59:16 +04:00
{
ClassFile . InnerClass [ ] innerClasses = classFile . InnerClasses ;
if ( innerClasses ! = null )
{
for ( int j = 0 ; j < innerClasses . Length ; j + + )
{
2006-05-15 13:08:01 +04:00
if ( innerClasses [ j ] . innerClass ! = 0
2005-08-03 16:59:16 +04:00
& & classFile . GetConstantPoolClass ( innerClasses [ j ] . innerClass ) = = classFile . Name )
{
2006-05-15 13:08:01 +04:00
return innerClasses [ j ] ;
2005-08-03 16:59:16 +04:00
}
}
}
2006-05-15 13:08:01 +04:00
return new ClassFile . InnerClass ( ) ;
2005-08-03 16:59:16 +04:00
}
2005-06-01 13:49:30 +04:00
private bool IsSideEffectFreeStaticInitializer ( ClassFile . Method m )
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if ( m . ExceptionTable . Length ! = 0 )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return false ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < m . Instructions . Length ; i + + )
2004-09-15 17:35:44 +04:00
{
2005-07-20 14:47:59 +04:00
NormalizedByteCode bc = m . Instructions [ i ] . NormalizedOpCode ;
if ( bc = = NormalizedByteCode . __getstatic | | bc = = NormalizedByteCode . __putstatic )
2005-06-01 13:49:30 +04:00
{
2006-06-22 14:04:07 +04:00
ClassFile . ConstantPoolItemFieldref fld = classFile . SafeGetFieldref ( m . Instructions [ i ] . Arg1 ) ;
if ( fld = = null | | fld . Class ! = classFile . Name )
2005-06-01 13:49:30 +04:00
{
return false ;
}
// don't allow getstatic to load non-primitive fields, because that would
// cause the verifier to try to load the type
2005-07-20 14:47:59 +04:00
if ( bc = = NormalizedByteCode . __getstatic & & "L[" . IndexOf ( fld . Signature [ 0 ] ) ! = - 1 )
2005-06-01 13:49:30 +04:00
{
return false ;
}
}
2005-07-20 14:47:59 +04:00
else if ( bc = = NormalizedByteCode . __areturn | |
bc = = NormalizedByteCode . __ireturn | |
bc = = NormalizedByteCode . __lreturn | |
bc = = NormalizedByteCode . __freturn | |
bc = = NormalizedByteCode . __dreturn )
2004-09-15 17:35:44 +04:00
{
return false ;
}
2005-06-01 13:49:30 +04:00
else if ( ByteCodeMetaData . CanThrowException ( bc ) )
2004-09-15 17:35:44 +04:00
{
return false ;
}
2006-06-22 14:04:07 +04:00
else if ( bc = = NormalizedByteCode . __ldc
& & classFile . SafeIsConstantPoolClass ( m . Instructions [ i ] . Arg1 ) )
{
return false ;
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
// the method needs to be verifiable to be side effect free, since we already analysed it,
// we know that the verifier won't try to load any types (which isn't allowed at this time)
try
2004-09-15 17:35:44 +04:00
{
2006-08-29 10:28:34 +04:00
new MethodAnalyzer ( wrapper , null , classFile , m , wrapper . classLoader ) ;
2005-06-01 13:49:30 +04:00
return true ;
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
catch ( VerifyError )
2004-09-15 17:35:44 +04:00
{
return false ;
}
}
2008-08-15 16:01:06 +04:00
private static bool ContainsMemberWrapper ( List < FieldWrapper > members , string name , string sig )
{
foreach ( MemberWrapper mw in members )
{
if ( mw . Name = = name & & mw . Signature = = sig )
{
return true ;
}
}
return false ;
}
private static bool ContainsMemberWrapper ( List < MethodWrapper > members , string name , string sig )
2005-08-14 19:49:50 +04:00
{
foreach ( MemberWrapper mw in members )
{
if ( mw . Name = = name & & mw . Signature = = sig )
{
return true ;
}
}
return false ;
}
2008-05-20 11:43:42 +04:00
#endif // STATIC_COMPILER
2005-08-14 19:49:50 +04:00
2008-08-15 16:01:06 +04:00
private MethodWrapper GetMethodWrapperDuringCtor ( TypeWrapper lookup , List < MethodWrapper > methods , string name , string sig )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( lookup = = wrapper )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper mw in methods )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( mw . Name = = name & & mw . Signature = = sig )
{
return mw ;
}
}
if ( lookup . BaseTypeWrapper = = null )
{
return null ;
}
else
{
return lookup . BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
2005-01-03 11:26:21 +03:00
}
}
else
{
2005-06-01 13:49:30 +04:00
return lookup . GetMethodWrapper ( name , sig , true ) ;
2005-01-03 11:26:21 +03:00
}
}
2008-08-15 16:01:06 +04:00
private void AddMirandaMethods ( List < MethodWrapper > methods , List < MethodWrapper > baseMethods , TypeWrapper tw )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( TypeWrapper iface in tw . Interfaces )
2004-08-17 13:05:21 +04:00
{
2007-08-03 17:14:41 +04:00
if ( iface . IsPublic & & this . wrapper . IsInterface )
{
// for interfaces, we only need miranda methods for non-public interfaces that we extend
continue ;
}
2005-06-01 13:49:30 +04:00
AddMirandaMethods ( methods , baseMethods , iface ) ;
foreach ( MethodWrapper ifmethod in iface . GetMethods ( ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// skip <clinit>
if ( ! ifmethod . IsStatic )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper lookup = wrapper ;
while ( lookup ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper mw = GetMethodWrapperDuringCtor ( lookup , methods , ifmethod . Name , ifmethod . Signature ) ;
if ( mw = = null )
{
mw = new SmartCallMethodWrapper ( wrapper , ifmethod . Name , ifmethod . Signature , null , null , null , Modifiers . Public | Modifiers . Abstract , MemberFlags . HideFromReflection | MemberFlags . MirandaMethod , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
methods . Add ( mw ) ;
baseMethods . Add ( ifmethod ) ;
break ;
}
if ( ! mw . IsStatic )
{
break ;
}
lookup = mw . DeclaringType . BaseTypeWrapper ;
2004-08-17 13:05:21 +04:00
}
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-02-20 17:18:38 +03:00
2008-05-20 11:43:42 +04:00
#if STATIC_COMPILER
2008-08-15 16:01:06 +04:00
private void AddAccessStubMethods ( List < MethodWrapper > methods , List < MethodWrapper > baseMethods , TypeWrapper tw )
2005-08-14 19:49:50 +04:00
{
foreach ( MethodWrapper mw in tw . GetMethods ( ) )
{
if ( ( mw . IsPublic | | mw . IsProtected )
& & mw . Name ! = "<init>"
& & ! ContainsMemberWrapper ( methods , mw . Name , mw . Signature ) )
{
MethodWrapper stub = new SmartCallMethodWrapper ( wrapper , mw . Name , mw . Signature , null , null , null , mw . Modifiers , MemberFlags . HideFromReflection | MemberFlags . AccessStub , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
methods . Add ( stub ) ;
baseMethods . Add ( mw ) ;
}
}
}
2008-08-15 16:01:06 +04:00
private void AddAccessStubFields ( List < FieldWrapper > fields , TypeWrapper tw )
2005-08-14 19:49:50 +04:00
{
do
{
if ( ! tw . IsPublic )
{
foreach ( FieldWrapper fw in tw . GetFields ( ) )
{
if ( ( fw . IsPublic | | fw . IsProtected )
& & ! ContainsMemberWrapper ( fields , fw . Name , fw . Signature ) )
{
fields . Add ( new AotAccessStubFieldWrapper ( wrapper , fw ) ) ;
}
}
}
foreach ( TypeWrapper iface in tw . Interfaces )
{
AddAccessStubFields ( fields , iface ) ;
}
tw = tw . BaseTypeWrapper ;
} while ( tw ! = null & & ! tw . IsPublic ) ;
}
2005-06-01 13:49:30 +04:00
private static bool CheckInnerOuterNames ( string inner , string outer )
{
// do some sanity checks on the inner/outer class names
2006-08-14 11:57:03 +04:00
return inner . Length > outer . Length + 1 & & inner [ outer . Length ] = = '$' & & inner . StartsWith ( outer ) ;
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
private static string GetInnerClassName ( string outer , string inner )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( CheckInnerOuterNames ( inner , outer ) ) ;
2006-08-14 11:57:03 +04:00
return DynamicClassLoader . EscapeName ( inner . Substring ( outer . Length + 1 ) ) ;
2003-11-17 15:01:50 +03:00
}
2008-05-20 11:43:42 +04:00
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
2005-06-01 13:49:30 +04:00
private int GetMethodIndex ( MethodWrapper mw )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < methods . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( methods [ i ] = = mw )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return i ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
}
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
Debug . Assert ( mw ! = null ) ;
bool unloadableOverrideStub = false ;
int index = GetMethodIndex ( mw ) ;
MethodWrapper baseMethod = baseMethods [ index ] ;
if ( baseMethod ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
baseMethod . Link ( ) ;
// check the loader constraints
if ( mw . ReturnType ! = baseMethod . ReturnType )
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if ( baseMethod . ReturnType . IsUnloadable | | JVM . FinishingForDebugSave )
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if ( ! mw . ReturnType . IsUnloadable | | ( ! baseMethod . ReturnType . IsUnloadable & & JVM . FinishingForDebugSave ) )
2004-08-17 13:05:21 +04:00
{
unloadableOverrideStub = true ;
}
}
else
{
2007-02-01 10:13:02 +03:00
#if STATIC_COMPILER
StaticCompiler . LinkageError ( "Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"" , mw . ReturnType , baseMethod . ReturnType , mw . DeclaringType . Name , mw . Name , mw . Signature , baseMethod . DeclaringType . Name ) ;
#endif
2004-08-17 13:05:21 +04:00
throw new LinkageError ( "Loader constraints violated" ) ;
}
}
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] here = mw . GetParameters ( ) ;
TypeWrapper [ ] there = baseMethod . GetParameters ( ) ;
for ( int i = 0 ; i < here . Length ; i + + )
{
if ( here [ i ] ! = there [ i ] )
{
2005-08-05 12:40:54 +04:00
if ( there [ i ] . IsUnloadable | | JVM . FinishingForDebugSave )
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if ( ! here [ i ] . IsUnloadable | | ( ! there [ i ] . IsUnloadable & & JVM . FinishingForDebugSave ) )
2005-06-01 13:49:30 +04:00
{
unloadableOverrideStub = true ;
}
}
else
{
2007-02-01 10:13:02 +03:00
#if STATIC_COMPILER
StaticCompiler . LinkageError ( "Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"" , here [ i ] , there [ i ] , mw . DeclaringType . Name , mw . Name , mw . Signature , baseMethod . DeclaringType . Name ) ;
#endif
2005-06-01 13:49:30 +04:00
throw new LinkageError ( "Loader constraints violated" ) ;
}
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
Debug . Assert ( mw . GetMethod ( ) = = null ) ;
MethodBase mb = GenerateMethod ( index , unloadableOverrideStub ) ;
if ( ( mw . Modifiers & ( Modifiers . Synchronized | Modifiers . Static ) ) = = Modifiers . Synchronized )
{
// note that constructors cannot be synchronized in Java
MethodBuilder mbld = ( MethodBuilder ) mb ;
mbld . SetImplementationFlags ( mbld . GetMethodImplementationFlags ( ) | MethodImplAttributes . Synchronized ) ;
}
return mb ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private int GetFieldIndex ( FieldWrapper fw )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < fields . Length ; i + + )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if ( fields [ i ] = = fw )
{
return i ;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField ( FieldWrapper fw )
2005-01-03 11:26:21 +03:00
{
2005-08-14 19:49:50 +04:00
if ( fw . IsAccessStub )
{
( ( AotAccessStubFieldWrapper ) fw ) . DoLink ( typeBuilder ) ;
return null ;
}
2008-04-14 09:13:41 +04:00
if ( fw is DynamicPropertyFieldWrapper )
{
( ( DynamicPropertyFieldWrapper ) fw ) . DoLink ( typeBuilder ) ;
return null ;
}
2007-06-28 14:32:50 +04:00
int fieldIndex = GetFieldIndex ( fw ) ;
#if STATIC_COMPILER
if ( fieldIndex > = classFile . Fields . Length )
{
// this must be a field defined in map.xml
FieldAttributes fieldAttribs = 0 ;
if ( fw . IsPublic )
{
fieldAttribs | = FieldAttributes . Public ;
}
else if ( fw . IsProtected )
{
fieldAttribs | = FieldAttributes . FamORAssem ;
}
else if ( fw . IsPrivate )
{
fieldAttribs | = FieldAttributes . Private ;
}
else
{
fieldAttribs | = FieldAttributes . Assembly ;
}
if ( fw . IsStatic )
{
fieldAttribs | = FieldAttributes . Static ;
}
if ( fw . IsFinal )
{
fieldAttribs | = FieldAttributes . InitOnly ;
}
return typeBuilder . DefineField ( fw . Name , fw . FieldTypeWrapper . TypeAsSignatureType , fieldAttribs ) ;
}
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
FieldBuilder field ;
2007-06-28 14:32:50 +04:00
ClassFile . Field fld = classFile . Fields [ fieldIndex ] ;
2005-06-01 13:49:30 +04:00
string fieldName = fld . Name ;
TypeWrapper typeWrapper = fw . FieldTypeWrapper ;
Type type = typeWrapper . TypeAsSignatureType ;
2006-10-04 13:03:18 +04:00
bool setNameSig = typeWrapper . IsErasedOrBoxedPrimitiveOrRemapped ;
2005-06-01 13:49:30 +04:00
if ( setNameSig )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO use clashtable
// the field name is mangled here, because otherwise it can (theoretically)
// conflict with another unloadable or object or ghost array field
// (fields can be overloaded on type)
fieldName + = "/" + typeWrapper . Name ;
}
FieldAttributes attribs = 0 ;
2005-09-01 11:34:53 +04:00
MethodAttributes methodAttribs = MethodAttributes . HideBySig ;
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
bool setModifiers = fld . IsInternal | | ( fld . Modifiers & ( Modifiers . Synthetic | Modifiers . Enum ) ) ! = 0 ;
#endif
bool isWrappedFinal = false ;
2005-06-01 13:49:30 +04:00
if ( fld . IsPrivate )
{
attribs | = FieldAttributes . Private ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( fld . IsProtected )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . FamORAssem ;
methodAttribs | = MethodAttributes . FamORAssem ;
2005-01-03 11:26:21 +03:00
}
2006-04-05 12:18:58 +04:00
else if ( fld . IsPublic )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . Public ;
methodAttribs | = MethodAttributes . Public ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
{
attribs | = FieldAttributes . Assembly ;
methodAttribs | = MethodAttributes . Assembly ;
}
if ( fld . IsStatic )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs | = FieldAttributes . Static ;
methodAttribs | = MethodAttributes . Static ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE "constant" static finals are converted into literals
// TODO it would be possible for Java code to change the value of a non-blank static final, but I don't
// know if we want to support this (since the Java JITs don't really support it either)
object constantValue = fld . ConstantValue ;
if ( fld . IsStatic & & fld . IsFinal & & constantValue ! = null )
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler . Count ( "Static Final Constant" ) ;
attribs | = FieldAttributes . Literal ;
field = typeBuilder . DefineField ( fieldName , type , attribs ) ;
field . SetConstant ( constantValue ) ;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
2005-01-03 11:26:21 +03:00
{
2005-07-07 17:10:09 +04:00
if ( fld . IsFinal )
2005-01-03 11:26:21 +03:00
{
2006-10-04 13:03:18 +04:00
isWrappedFinal = fw is GetterFieldWrapper ;
2005-07-07 17:10:09 +04:00
if ( isWrappedFinal )
2005-06-01 13:49:30 +04:00
{
// NOTE public/protected blank final fields get converted into a read-only property with a private field
// backing store
attribs & = ~ FieldAttributes . FieldAccessMask ;
2006-08-15 12:50:43 +04:00
attribs | = FieldAttributes . PrivateScope ;
2005-06-01 13:49:30 +04:00
}
2006-08-29 10:28:34 +04:00
else if ( wrapper . IsInterface | | wrapper . classLoader . StrictFinalFieldSemantics )
2005-07-07 17:10:09 +04:00
{
attribs | = FieldAttributes . InitOnly ;
}
else
{
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
2005-07-07 17:10:09 +04:00
setModifiers = true ;
2006-10-04 13:03:18 +04:00
#endif
2005-07-07 17:10:09 +04:00
}
2005-06-01 13:49:30 +04:00
}
2006-10-04 16:51:19 +04:00
Type [ ] modreq = Type . EmptyTypes ;
if ( fld . IsVolatile )
{
modreq = new Type [ ] { typeof ( System . Runtime . CompilerServices . IsVolatile ) } ;
}
2008-08-06 09:48:52 +04:00
field = typeBuilder . DefineField ( fieldName , type , modreq , Type . EmptyTypes , attribs ) ;
2005-06-01 13:49:30 +04:00
if ( fld . IsTransient )
{
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder ( typeof ( NonSerializedAttribute ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
field . SetCustomAttribute ( transientAttrib ) ;
}
2006-08-17 17:18:45 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// Instance fields can also have a ConstantValue attribute (and are inlined by the compiler),
// and ikvmstub has to export them, so we have to add a custom attribute.
if ( constantValue ! = null )
{
2005-12-07 12:06:32 +03:00
AttributeHelper . SetConstantValue ( field , constantValue ) ;
2005-06-01 13:49:30 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if ( isWrappedFinal )
{
methodAttribs | = MethodAttributes . SpecialName ;
2006-08-15 12:50:43 +04:00
MethodBuilder getter = typeBuilder . DefineMethod ( GenerateUniqueMethodName ( "get_" + fieldName , type , Type . EmptyTypes ) , methodAttribs , CallingConventions . Standard , type , Type . EmptyTypes ) ;
2005-06-01 13:49:30 +04:00
AttributeHelper . HideFromJava ( getter ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( getter ) ;
2005-06-01 13:49:30 +04:00
if ( fld . IsStatic )
{
ilgen . Emit ( OpCodes . Ldsfld , field ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldfld , field ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
2006-10-04 13:03:18 +04:00
2006-08-15 12:50:43 +04:00
PropertyBuilder pb = typeBuilder . DefineProperty ( fieldName , PropertyAttributes . None , type , Type . EmptyTypes ) ;
2005-06-01 13:49:30 +04:00
pb . SetGetMethod ( getter ) ;
2006-08-15 12:50:43 +04:00
if ( ! fld . IsStatic )
{
// this method exist for use by reflection only
// (that's why it only exists for instance fields, final static fields are not settable by reflection)
MethodBuilder setter = typeBuilder . DefineMethod ( "__<set>" , MethodAttributes . PrivateScope , CallingConventions . Standard , typeof ( void ) , new Type [ ] { type } ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( setter ) ;
2006-08-15 12:50:43 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Stfld , field ) ;
ilgen . Emit ( OpCodes . Ret ) ;
pb . SetSetMethod ( setter ) ;
}
2005-06-01 13:49:30 +04:00
( ( GetterFieldWrapper ) fw ) . SetGetter ( getter ) ;
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
if ( setNameSig )
{
AttributeHelper . SetNameSig ( getter , fld . Name , fld . Signature ) ;
}
if ( setModifiers | | fld . IsTransient )
{
AttributeHelper . SetModifiers ( getter , fld . Modifiers , fld . IsInternal ) ;
}
if ( fld . DeprecatedAttribute )
{
// NOTE for better interop with other languages, we set the ObsoleteAttribute on the property itself
AttributeHelper . SetDeprecatedAttribute ( pb ) ;
}
if ( fld . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( getter , fld . GenericSignature ) ;
}
#endif // STATIC_COMPILER
2005-01-03 11:26:21 +03:00
}
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
2006-10-04 13:03:18 +04:00
if ( ! isWrappedFinal )
2006-05-04 12:09:56 +04:00
{
2006-10-04 13:03:18 +04:00
// if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store
// the Java modifiers
if ( setModifiers )
{
AttributeHelper . SetModifiers ( field , fld . Modifiers , fld . IsInternal ) ;
}
if ( setNameSig )
{
AttributeHelper . SetNameSig ( field , fld . Name , fld . Signature ) ;
}
if ( fld . DeprecatedAttribute )
{
AttributeHelper . SetDeprecatedAttribute ( field ) ;
}
if ( fld . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( field , fld . GenericSignature ) ;
}
2006-08-17 17:18:45 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
return field ;
2005-01-03 11:26:21 +03:00
}
2004-08-17 13:05:21 +04:00
2008-06-03 16:10:07 +04:00
internal override void EmitRunClassConstructor ( CodeEmitter ilgen )
2005-08-24 12:14:23 +04:00
{
if ( clinitMethod ! = null )
{
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
}
}
2005-08-05 12:40:54 +04:00
internal override DynamicImpl Finish ( )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( wrapper . BaseTypeWrapper ! = null )
{
2005-08-05 12:40:54 +04:00
wrapper . BaseTypeWrapper . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if ( outerClassWrapper ! = null )
{
2005-08-05 12:40:54 +04:00
outerClassWrapper . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that
// causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types.
// The Name in the ResolveEventArgs contains only the nested type name, not the full type name,
// for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only
// receives "MyInnerType" as the name. Since we only compile inner classes as nested types
// when we're statically compiling, we can only run into this bug when we're statically compiling.
// NOTE To work around this bug, we have to make sure that all types that are going to be
// required in finished form, are finished explicitly here. It isn't clear what other types are
// required to be finished. I instrumented a static compilation of classpath.dll and this
// turned up no other cases of the TypeResolve event firing.
for ( int i = 0 ; i < wrapper . Interfaces . Length ; i + + )
{
2005-08-05 12:40:54 +04:00
wrapper . Interfaces [ i ] . Finish ( ) ;
2005-06-01 13:49:30 +04:00
}
// make sure all classes are loaded, before we start finishing the type. During finishing, we
// may not run any Java code, because that might result in a request to finish the type that we
// are in the process of finishing, and this would be a problem.
2008-08-15 10:27:12 +04:00
classFile . Link ( wrapper ) ;
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < fields . Length ; i + + )
{
2007-07-31 19:27:22 +04:00
#if STATIC_COMPILER
if ( fields [ i ] is AotAccessStubFieldWrapper )
{
// HACK we skip access stubs, because we want to do the methods first
// (to prevent the stub method from taking the name of a real method)
continue ;
}
#endif
2005-06-01 13:49:30 +04:00
fields [ i ] . Link ( ) ;
}
for ( int i = 0 ; i < methods . Length ; i + + )
{
methods [ i ] . Link ( ) ;
}
2007-07-31 19:27:22 +04:00
#if STATIC_COMPILER
// HACK second pass for the access stubs (see above)
for ( int i = 0 ; i < fields . Length ; i + + )
{
if ( fields [ i ] is AotAccessStubFieldWrapper )
{
fields [ i ] . Link ( ) ;
}
}
#endif
2006-05-05 15:21:15 +04:00
// this is the correct lock, FinishCore doesn't call any user code and mutates global state,
// so it needs to be protected by a lock.
lock ( this )
{
return FinishCore ( ) ;
}
}
private FinishedTypeImpl FinishCore ( )
{
2005-06-01 13:49:30 +04:00
// it is possible that the loading of the referenced classes triggered a finish of us,
// if that happens, we just return
if ( finishedType ! = null )
{
return finishedType ;
}
2008-02-29 10:08:04 +03:00
if ( finishInProgress )
{
throw new InvalidOperationException ( "Recursive finish attempt for " + wrapper . Name ) ;
}
finishInProgress = true ;
2006-08-14 11:57:03 +04:00
Tracer . Info ( Tracer . Compiler , "Finishing: {0}" , wrapper . Name ) ;
2005-06-01 13:49:30 +04:00
Profiler . Enter ( "JavaTypeImpl.Finish.Core" ) ;
try
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper declaringTypeWrapper = null ;
TypeWrapper [ ] innerClassesTypeWrappers = TypeWrapper . EmptyArray ;
// if we're an inner class, we need to attach an InnerClass attribute
ClassFile . InnerClass [ ] innerclasses = classFile . InnerClasses ;
2008-06-03 10:52:30 +04:00
if ( innerclasses ! = null )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here
2008-08-15 16:01:06 +04:00
List < TypeWrapper > wrappers = new List < TypeWrapper > ( ) ;
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < innerclasses . Length ; i + + )
2003-10-17 12:08:31 +04:00
{
2008-06-03 10:52:30 +04:00
if ( innerclasses [ i ] . innerClass ! = 0 & & innerclasses [ i ] . outerClass ! = 0 )
2003-10-17 12:08:31 +04:00
{
2008-06-03 10:52:30 +04:00
if ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . outerClass ) = = wrapper )
2005-06-01 13:49:30 +04:00
{
wrappers . Add ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . innerClass ) ) ;
}
2008-06-03 10:52:30 +04:00
if ( classFile . GetConstantPoolClassType ( innerclasses [ i ] . innerClass ) = = wrapper )
2005-06-01 13:49:30 +04:00
{
declaringTypeWrapper = classFile . GetConstantPoolClassType ( innerclasses [ i ] . outerClass ) ;
}
2003-10-17 12:08:31 +04:00
}
}
2008-08-15 16:01:06 +04:00
innerClassesTypeWrappers = wrappers . ToArray ( ) ;
2008-07-02 10:22:21 +04:00
#if STATIC_COMPILER
// before we bake our type, we need to link any inner annotations to allow them to create their attribute type (as a nested type)
foreach ( TypeWrapper tw in innerClassesTypeWrappers )
{
DynamicTypeWrapper dtw = tw as DynamicTypeWrapper ;
if ( dtw ! = null )
{
JavaTypeImpl impl = dtw . impl as JavaTypeImpl ;
if ( impl ! = null )
{
if ( impl . annotationBuilder ! = null )
{
impl . annotationBuilder . Link ( ) ;
}
}
}
}
#endif //STATIC_COMPILER
2003-10-17 12:08:31 +04:00
}
2008-06-03 10:52:30 +04:00
FinishContext context = new FinishContext ( classFile , wrapper , typeBuilder ) ;
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
2008-07-02 10:22:21 +04:00
if ( annotationBuilder ! = null )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( JVM . LoadType ( typeof ( AnnotationAttributeAttribute ) ) . GetConstructor ( new Type [ ] { typeof ( string ) } ) , new object [ ] { annotationBuilder . AttributeTypeName } ) ;
typeBuilder . SetCustomAttribute ( cab ) ;
}
2008-06-03 10:52:30 +04:00
context . RegisterPostFinishProc ( delegate
{
if ( enumBuilder ! = null )
{
enumBuilder . CreateType ( ) ;
}
if ( annotationBuilder ! = null )
{
annotationBuilder . Finish ( this ) ;
}
} ) ;
#endif
Type type = context . FinishImpl ( ) ;
2008-12-01 08:26:28 +03:00
MethodInfo finishedClinitMethod = clinitMethod ;
#if ! STATIC_COMPILER
if ( finishedClinitMethod ! = null )
{
// In dynamic mode, we may need to emit a call to this method from a DynamicMethod which doesn't support calling unfinished methods,
// so we must resolve to the real method here.
finishedClinitMethod = type . GetMethod ( "__<clinit>" , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
}
#endif
finishedType = new FinishedTypeImpl ( type , innerClassesTypeWrappers , declaringTypeWrapper , wrapper . ReflectiveModifiers , Metadata . Create ( classFile ) , finishedClinitMethod , finalizeMethod
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
, annotationBuilder , enumBuilder
#endif
) ;
return finishedType ;
}
catch ( Exception x )
{
JVM . CriticalFailure ( "Exception during finishing of: " + wrapper . Name , x ) ;
return null ;
}
finally
{
Profiler . Leave ( "JavaTypeImpl.Finish.Core" ) ;
}
}
#if STATIC_COMPILER
private bool IsValidAnnotationElementType ( string type )
{
if ( type [ 0 ] = = '[' )
{
type = type . Substring ( 1 ) ;
}
switch ( type )
{
case "Z" :
case "B" :
case "S" :
case "C" :
case "I" :
case "J" :
case "F" :
case "D" :
case "Ljava.lang.String;" :
case "Ljava.lang.Class;" :
return true ;
}
if ( type . StartsWith ( "L" ) & & type . EndsWith ( ";" ) )
{
try
2003-10-17 12:08:31 +04:00
{
2008-06-03 10:52:30 +04:00
TypeWrapper tw = wrapper . GetClassLoader ( ) . LoadClassByDottedNameFast ( type . Substring ( 1 , type . Length - 2 ) ) ;
if ( tw ! = null )
2003-10-17 12:08:31 +04:00
{
2008-06-03 10:52:30 +04:00
if ( ( tw . Modifiers & Modifiers . Annotation ) ! = 0 )
{
return true ;
}
if ( ( tw . Modifiers & Modifiers . Enum ) ! = 0 )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
TypeWrapper enumType = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( "java.lang.Enum" ) ;
if ( enumType ! = null & & tw . IsSubTypeOf ( enumType ) )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
return true ;
2005-06-01 13:49:30 +04:00
}
}
2003-01-02 18:44:17 +03:00
}
2002-12-18 19:00:25 +03:00
}
2008-06-03 10:52:30 +04:00
catch
{
}
}
return false ;
}
sealed class AnnotationBuilder : Annotation
{
2008-07-02 10:22:21 +04:00
private JavaTypeImpl impl ;
2008-06-03 10:52:30 +04:00
private TypeBuilder annotationTypeBuilder ;
private TypeBuilder attributeTypeBuilder ;
private ConstructorBuilder defineConstructor ;
internal AnnotationBuilder ( JavaTypeImpl o )
{
2008-07-02 10:22:21 +04:00
this . impl = o ;
}
internal void Link ( )
{
if ( impl = = null )
{
return ;
}
JavaTypeImpl o = impl ;
impl = null ;
2008-06-03 10:52:30 +04:00
// Make sure the annotation type only has valid methods
for ( int i = 0 ; i < o . methods . Length ; i + + )
2002-12-18 19:00:25 +03:00
{
2008-06-03 10:52:30 +04:00
if ( ! o . methods [ i ] . IsStatic )
2002-12-18 19:00:25 +03:00
{
2008-06-03 10:52:30 +04:00
if ( ! o . methods [ i ] . Signature . StartsWith ( "()" ) )
2003-01-02 18:44:17 +03:00
{
2008-06-03 10:52:30 +04:00
return ;
2006-08-14 11:57:03 +04:00
}
2008-06-03 10:52:30 +04:00
if ( ! o . IsValidAnnotationElementType ( o . methods [ i ] . Signature . Substring ( 2 ) ) )
2006-08-14 11:57:03 +04:00
{
2008-06-03 10:52:30 +04:00
return ;
2002-12-18 19:00:25 +03:00
}
2008-06-03 10:52:30 +04:00
}
}
// we only set annotationTypeBuilder if we're valid
annotationTypeBuilder = o . typeBuilder ;
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper . LoadClassCritical ( "ikvm.internal.AnnotationAttributeBase" ) ;
// TODO attribute should be .NET serializable
TypeAttributes typeAttributes = TypeAttributes . Class | TypeAttributes . Sealed ;
if ( o . outerClassWrapper ! = null )
{
if ( o . wrapper . IsPublic )
{
typeAttributes | = TypeAttributes . NestedPublic ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
typeAttributes | = TypeAttributes . NestedAssembly ;
}
attributeTypeBuilder = o . outerClassWrapper . TypeAsBuilder . DefineNestedType ( GetInnerClassName ( o . outerClassWrapper . Name , o . classFile . Name ) + "Attribute" , typeAttributes , annotationAttributeBaseType . TypeAsBaseType ) ;
}
else
{
if ( o . wrapper . IsPublic )
{
typeAttributes | = TypeAttributes . Public ;
}
else
{
typeAttributes | = TypeAttributes . NotPublic ;
}
attributeTypeBuilder = o . wrapper . classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . DefineType ( o . classFile . Name + "Attribute" , typeAttributes , annotationAttributeBaseType . TypeAsBaseType ) ;
}
if ( o . wrapper . IsPublic )
{
// In the Java world, the class appears as a non-public proxy class
AttributeHelper . SetModifiers ( attributeTypeBuilder , Modifiers . Final , false ) ;
}
// NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world
int dotindex = o . classFile . Name . LastIndexOf ( '.' ) + 1 ;
AttributeHelper . SetInnerClass ( attributeTypeBuilder , o . classFile . Name . Substring ( 0 , dotindex ) + "$Proxy" + o . classFile . Name . Substring ( dotindex ) , Modifiers . Final ) ;
attributeTypeBuilder . AddInterfaceImplementation ( o . typeBuilder ) ;
AttributeHelper . SetImplementsAttribute ( attributeTypeBuilder , new TypeWrapper [ ] { o . wrapper } ) ;
if ( o . classFile . Annotations ! = null )
{
foreach ( object [ ] def in o . classFile . Annotations )
{
if ( def [ 1 ] . Equals ( "Ljava/lang/annotation/Target;" ) )
{
for ( int i = 2 ; i < def . Length ; i + = 2 )
{
if ( def [ i ] . Equals ( "value" ) )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
object [ ] val = def [ i + 1 ] as object [ ] ;
if ( val ! = null
& & val . Length > 0
& & val [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ARRAY ) )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
AttributeTargets targets = 0 ;
for ( int j = 1 ; j < val . Length ; j + + )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
object [ ] eval = val [ j ] as object [ ] ;
if ( eval ! = null
& & eval . Length = = 3
& & eval [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ENUM )
& & eval [ 1 ] . Equals ( "Ljava/lang/annotation/ElementType;" ) )
{
switch ( ( string ) eval [ 2 ] )
{
case "ANNOTATION_TYPE" :
targets | = AttributeTargets . Interface ;
break ;
case "CONSTRUCTOR" :
targets | = AttributeTargets . Constructor ;
break ;
case "FIELD" :
targets | = AttributeTargets . Field ;
break ;
case "LOCAL_VARIABLE" :
break ;
case "METHOD" :
targets | = AttributeTargets . Method ;
break ;
case "PACKAGE" :
targets | = AttributeTargets . Interface ;
break ;
case "PARAMETER" :
targets | = AttributeTargets . Parameter ;
break ;
case "TYPE" :
targets | = AttributeTargets . Class | AttributeTargets . Interface | AttributeTargets . Struct | AttributeTargets . Delegate | AttributeTargets . Enum ;
break ;
}
}
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
CustomAttributeBuilder cab2 = new CustomAttributeBuilder ( typeof ( AttributeUsageAttribute ) . GetConstructor ( new Type [ ] { typeof ( AttributeTargets ) } ) , new object [ ] { targets } ) ;
attributeTypeBuilder . SetCustomAttribute ( cab2 ) ;
2004-08-17 13:05:21 +04:00
}
}
2003-01-02 18:44:17 +03:00
}
2005-03-01 11:24:54 +03:00
}
2002-12-27 12:01:16 +03:00
}
2003-01-02 18:44:17 +03:00
}
2007-03-11 17:14:52 +03:00
2008-06-03 10:52:30 +04:00
defineConstructor = attributeTypeBuilder . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard , new Type [ ] { typeof ( object [ ] ) } ) ;
AttributeHelper . SetEditorBrowsableNever ( defineConstructor ) ;
}
private static Type TypeWrapperToAnnotationParameterType ( TypeWrapper tw )
{
bool isArray = false ;
if ( tw . IsArray )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
isArray = true ;
tw = tw . ElementTypeWrapper ;
}
if ( tw . Annotation ! = null )
{
// we don't support Annotation args
return null ;
}
else
{
Type argType ;
if ( tw = = CoreClasses . java . lang . Class . Wrapper )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
argType = typeof ( Type ) ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
else if ( tw . EnumType ! = null )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
argType = tw . EnumType ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
else
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
argType = tw . TypeAsSignatureType ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
if ( isArray )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
argType = ArrayTypeWrapper . MakeArrayType ( argType , 1 ) ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
return argType ;
}
}
internal string AttributeTypeName
{
get
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( attributeTypeBuilder ! = null )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
return attributeTypeBuilder . FullName ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
return null ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
}
2008-05-31 19:20:29 +04:00
2008-06-03 16:10:07 +04:00
private static void EmitSetValueCall ( TypeWrapper annotationAttributeBaseType , CodeEmitter ilgen , string name , TypeWrapper tw , int argIndex )
2008-06-03 10:52:30 +04:00
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldstr , name ) ;
ilgen . Emit ( OpCodes . Ldarg_S , ( byte ) argIndex ) ;
if ( tw . TypeAsSignatureType . IsValueType )
{
ilgen . Emit ( OpCodes . Box , tw . TypeAsSignatureType ) ;
}
else if ( tw . EnumType ! = null )
{
ilgen . Emit ( OpCodes . Box , tw . EnumType ) ;
}
MethodWrapper setValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "setValue" , "(Ljava.lang.String;Ljava.lang.Object;)V" , false ) ;
setValueMethod . Link ( ) ;
setValueMethod . EmitCall ( ilgen ) ;
}
2007-03-11 17:14:52 +03:00
2008-06-03 10:52:30 +04:00
internal void Finish ( JavaTypeImpl o )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder = = null )
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
// not a valid annotation type
return ;
}
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper . LoadClassCritical ( "ikvm.internal.AnnotationAttributeBase" ) ;
annotationAttributeBaseType . Finish ( ) ;
2003-05-30 16:08:59 +04:00
2008-06-03 10:52:30 +04:00
int requiredArgCount = 0 ;
int valueArg = - 1 ;
bool unsupported = false ;
for ( int i = 0 ; i < o . methods . Length ; i + + )
{
if ( ! o . methods [ i ] . IsStatic )
2003-05-13 00:00:15 +04:00
{
2008-06-03 10:52:30 +04:00
if ( valueArg = = - 1 & & o . methods [ i ] . Name = = "value" )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
valueArg = i ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( o . classFile . Methods [ i ] . AnnotationDefault = = null )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
if ( TypeWrapperToAnnotationParameterType ( o . methods [ i ] . ReturnType ) = = null )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
unsupported = true ;
break ;
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
requiredArgCount + + ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
}
}
2008-06-03 10:52:30 +04:00
ConstructorBuilder defaultConstructor = attributeTypeBuilder . DefineConstructor ( unsupported | | requiredArgCount > 0 ? MethodAttributes . Private : MethodAttributes . Public , CallingConventions . Standard , Type . EmptyTypes ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen ;
2008-06-03 10:52:30 +04:00
if ( ! unsupported )
{
if ( requiredArgCount > 0 )
{
Type [ ] args = new Type [ requiredArgCount ] ;
for ( int i = 0 , j = 0 ; i < o . methods . Length ; i + + )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
if ( ! o . methods [ i ] . IsStatic )
{
if ( o . classFile . Methods [ i ] . AnnotationDefault = = null )
{
args [ j + + ] = TypeWrapperToAnnotationParameterType ( o . methods [ i ] . ReturnType ) ;
}
}
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
ConstructorBuilder reqArgConstructor = attributeTypeBuilder . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard , args ) ;
AttributeHelper . HideFromJava ( reqArgConstructor ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( reqArgConstructor ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , defaultConstructor ) ;
for ( int i = 0 , j = 0 ; i < o . methods . Length ; i + + )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
if ( ! o . methods [ i ] . IsStatic )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
if ( o . classFile . Methods [ i ] . AnnotationDefault = = null )
{
reqArgConstructor . DefineParameter ( + + j , ParameterAttributes . None , o . methods [ i ] . Name ) ;
EmitSetValueCall ( annotationAttributeBaseType , ilgen , o . methods [ i ] . Name , o . methods [ i ] . ReturnType , j ) ;
}
2004-08-17 13:05:21 +04:00
}
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ret ) ;
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
else if ( valueArg ! = - 1 )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
// We don't have any required parameters, but we do have an optional "value" parameter,
// so we create an additional constructor (the default constructor will be public in this case)
// that accepts the value parameter.
Type argType = TypeWrapperToAnnotationParameterType ( o . methods [ valueArg ] . ReturnType ) ;
if ( argType ! = null )
2007-05-10 10:53:50 +04:00
{
2008-06-03 10:52:30 +04:00
ConstructorBuilder cb = attributeTypeBuilder . DefineConstructor ( MethodAttributes . Public , CallingConventions . Standard , new Type [ ] { argType } ) ;
AttributeHelper . HideFromJava ( cb ) ;
cb . DefineParameter ( 1 , ParameterAttributes . None , "value" ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( cb ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , defaultConstructor ) ;
EmitSetValueCall ( annotationAttributeBaseType , ilgen , "value" , o . methods [ valueArg ] . ReturnType , 1 ) ;
ilgen . Emit ( OpCodes . Ret ) ;
2007-05-10 10:53:50 +04:00
}
}
2008-06-03 10:52:30 +04:00
}
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( defaultConstructor ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldtoken , annotationTypeBuilder ) ;
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . GetClassFromTypeHandle ) ;
CoreClasses . java . lang . Class . Wrapper . EmitCheckcast ( null , ilgen ) ;
annotationAttributeBaseType . GetMethodWrapper ( "<init>" , "(Ljava.lang.Class;)V" , false ) . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( defineConstructor ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , defaultConstructor ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
annotationAttributeBaseType . GetMethodWrapper ( "setDefinition" , "([Ljava.lang.Object;)V" , false ) . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
MethodWrapper getValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getValue" , "(Ljava.lang.String;)Ljava.lang.Object;" , false ) ;
MethodWrapper getByteValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getByteValue" , "(Ljava.lang.String;)B" , false ) ;
MethodWrapper getBooleanValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getBooleanValue" , "(Ljava.lang.String;)Z" , false ) ;
MethodWrapper getCharValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getCharValue" , "(Ljava.lang.String;)C" , false ) ;
MethodWrapper getShortValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getShortValue" , "(Ljava.lang.String;)S" , false ) ;
MethodWrapper getIntValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getIntValue" , "(Ljava.lang.String;)I" , false ) ;
MethodWrapper getFloatValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getFloatValue" , "(Ljava.lang.String;)F" , false ) ;
MethodWrapper getLongValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getLongValue" , "(Ljava.lang.String;)J" , false ) ;
MethodWrapper getDoubleValueMethod = annotationAttributeBaseType . GetMethodWrapper ( "getDoubleValue" , "(Ljava.lang.String;)D" , false ) ;
for ( int i = 0 ; i < o . methods . Length ; i + + )
{
// skip <clinit>
if ( ! o . methods [ i ] . IsStatic )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
MethodBuilder mb = attributeTypeBuilder . DefineMethod ( o . methods [ i ] . Name , MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . Final | MethodAttributes . NewSlot , o . methods [ i ] . ReturnTypeForDefineMethod , o . methods [ i ] . GetParametersForDefineMethod ( ) ) ;
attributeTypeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) o . methods [ i ] . GetMethod ( ) ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldstr , o . methods [ i ] . Name ) ;
if ( o . methods [ i ] . ReturnType . IsPrimitive )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . BYTE )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
getByteValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . BOOLEAN )
{
getBooleanValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . CHAR )
{
getCharValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . SHORT )
{
getShortValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . INT )
{
getIntValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . FLOAT )
{
getFloatValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . LONG )
{
getLongValueMethod . EmitCall ( ilgen ) ;
}
else if ( o . methods [ i ] . ReturnType = = PrimitiveTypeWrapper . DOUBLE )
{
getDoubleValueMethod . EmitCall ( ilgen ) ;
}
else
{
throw new InvalidOperationException ( ) ;
2007-04-15 12:01:19 +04:00
}
}
2008-06-03 10:52:30 +04:00
else
2007-04-15 12:01:19 +04:00
{
2008-06-03 10:52:30 +04:00
getValueMethod . EmitCall ( ilgen ) ;
o . methods [ i ] . ReturnType . EmitCheckcast ( null , ilgen ) ;
2007-04-15 12:01:19 +04:00
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ret ) ;
if ( o . classFile . Methods [ i ] . AnnotationDefault ! = null
& & ! ( o . methods [ i ] . Name = = "value" & & requiredArgCount = = 0 ) )
2007-04-15 12:01:19 +04:00
{
2008-06-03 10:52:30 +04:00
// now add a .NET property for this annotation optional parameter
Type argType = TypeWrapperToAnnotationParameterType ( o . methods [ i ] . ReturnType ) ;
if ( argType ! = null )
2007-04-15 12:01:19 +04:00
{
2008-06-03 10:52:30 +04:00
PropertyBuilder pb = attributeTypeBuilder . DefineProperty ( o . methods [ i ] . Name , PropertyAttributes . None , argType , Type . EmptyTypes ) ;
AttributeHelper . HideFromJava ( pb ) ;
MethodBuilder setter = attributeTypeBuilder . DefineMethod ( "set_" + o . methods [ i ] . Name , MethodAttributes . Public , typeof ( void ) , new Type [ ] { argType } ) ;
AttributeHelper . HideFromJava ( setter ) ;
pb . SetSetMethod ( setter ) ;
2008-06-03 16:10:07 +04:00
ilgen = CodeEmitter . Create ( setter ) ;
2008-06-03 10:52:30 +04:00
EmitSetValueCall ( annotationAttributeBaseType , ilgen , o . methods [ i ] . Name , o . methods [ i ] . ReturnType , 1 ) ;
ilgen . Emit ( OpCodes . Ret ) ;
MethodBuilder getter = attributeTypeBuilder . DefineMethod ( "get_" + o . methods [ i ] . Name , MethodAttributes . Public , argType , Type . EmptyTypes ) ;
AttributeHelper . HideFromJava ( getter ) ;
pb . SetGetMethod ( getter ) ;
// TODO implement the getter method
2008-06-03 16:10:07 +04:00
CodeEmitter . Create ( getter ) . ThrowException ( typeof ( NotImplementedException ) ) ;
2005-11-01 17:01:42 +03:00
}
2006-04-20 11:30:59 +04:00
}
}
2006-06-15 16:29:11 +04:00
}
2008-06-03 10:52:30 +04:00
attributeTypeBuilder . CreateType ( ) ;
}
2006-04-20 11:30:59 +04:00
2008-06-03 10:52:30 +04:00
internal override void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
2006-06-15 16:29:11 +04:00
{
2008-06-03 10:52:30 +04:00
annotation = QualifyClassNames ( loader , annotation ) ;
tb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
2006-06-15 16:29:11 +04:00
}
2008-06-03 10:52:30 +04:00
}
2006-04-20 11:30:59 +04:00
2008-06-03 10:52:30 +04:00
internal override void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
2006-06-15 16:29:11 +04:00
{
2008-06-03 10:52:30 +04:00
annotation = QualifyClassNames ( loader , annotation ) ;
mb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
2005-10-01 15:16:11 +04:00
}
2008-06-03 10:52:30 +04:00
}
2005-10-01 15:16:11 +04:00
2008-06-03 10:52:30 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
2005-01-03 11:26:21 +03:00
{
2008-06-03 10:52:30 +04:00
annotation = QualifyClassNames ( loader , annotation ) ;
cb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
2005-01-03 11:26:21 +03:00
}
2008-06-03 10:52:30 +04:00
}
internal override void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
2005-01-03 11:26:21 +03:00
{
2008-06-03 10:52:30 +04:00
annotation = QualifyClassNames ( loader , annotation ) ;
fb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
2005-01-03 11:26:21 +03:00
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation )
2005-11-01 17:01:42 +03:00
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
{
annotation = QualifyClassNames ( loader , annotation ) ;
pb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
internal override void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation )
2005-11-01 17:01:42 +03:00
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
{
annotation = QualifyClassNames ( loader , annotation ) ;
ab . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation )
{
2008-07-02 10:22:21 +04:00
Link ( ) ;
2008-06-03 10:52:30 +04:00
if ( annotationTypeBuilder ! = null )
{
annotation = QualifyClassNames ( loader , annotation ) ;
pb . SetCustomAttribute ( new CustomAttributeBuilder ( defineConstructor , new object [ ] { annotation } ) ) ;
}
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
#endif // STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2008-06-03 10:52:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
get
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
throw new InvalidOperationException ( "InnerClasses is only available for finished types" ) ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
throw new InvalidOperationException ( "DeclaringTypeWrapper is only available for finished types" ) ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
}
internal override Modifiers ReflectiveModifiers
{
get
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
ClassFile . InnerClass [ ] innerclasses = classFile . InnerClasses ;
if ( innerclasses ! = null )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < innerclasses . Length ; i + + )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
if ( innerclasses [ i ] . innerClass ! = 0 )
{
if ( classFile . GetConstantPoolClass ( innerclasses [ i ] . innerClass ) = = wrapper . Name )
{
return innerclasses [ i ] . accessFlags ;
}
}
2008-05-31 19:20:29 +04:00
}
}
2008-06-03 10:52:30 +04:00
return classFile . Modifiers ;
2008-05-31 19:20:29 +04:00
}
}
2008-06-03 10:52:30 +04:00
private void UpdateClashTable ( )
2007-12-28 13:22:06 +03:00
{
lock ( this )
{
2008-06-03 10:52:30 +04:00
if ( memberclashtable = = null )
2007-12-28 13:22:06 +03:00
{
2008-08-15 16:01:06 +04:00
memberclashtable = new Dictionary < string , string > ( ) ;
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < methods . Length ; i + + )
{
// TODO at the moment we don't support constructor signature clash resolving, so we better
// not put them in the clash table
if ( methods [ i ] . IsLinked & & methods [ i ] . GetMethod ( ) ! = null & & methods [ i ] . Name ! = "<init>" )
{
string key = GenerateClashKey ( "method" , methods [ i ] . RealName , methods [ i ] . ReturnTypeForDefineMethod , methods [ i ] . GetParametersForDefineMethod ( ) ) ;
memberclashtable . Add ( key , key ) ;
}
}
2007-12-28 13:22:06 +03:00
}
}
}
2008-06-03 10:52:30 +04:00
private static string GenerateClashKey ( string type , string name , Type retOrFieldType , Type [ ] args )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( type ) ;
sb . Append ( ':' ) . Append ( name ) . Append ( ':' ) . Append ( retOrFieldType . FullName ) ;
if ( args ! = null )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( Type t in args )
2008-05-31 19:20:29 +04:00
{
2008-06-03 10:52:30 +04:00
sb . Append ( ':' ) . Append ( t . FullName ) ;
2008-05-31 19:20:29 +04:00
}
}
2008-06-03 10:52:30 +04:00
return sb . ToString ( ) ;
2008-05-31 19:20:29 +04:00
}
2008-06-03 10:52:30 +04:00
internal static ConstructorBuilder DefineClassInitializer ( TypeBuilder typeBuilder )
2007-03-11 17:14:52 +03:00
{
2008-06-03 10:52:30 +04:00
if ( typeBuilder . IsInterface )
2007-03-11 17:14:52 +03:00
{
2008-06-03 10:52:30 +04:00
// LAMESPEC the ECMA spec says (part. I, sect. 8.5.3.2) that all interface members must be public, so we make
// the class constructor public.
// NOTE it turns out that on .NET 2.0 this isn't necessary anymore (neither Ref.Emit nor the CLR verifier complain about it),
// but the C# compiler still considers interfaces with non-public methods to be invalid, so to keep interop with C# we have
// to keep making the .cctor method public.
return typeBuilder . DefineConstructor ( MethodAttributes . Static | MethodAttributes . Public , CallingConventions . Standard , Type . EmptyTypes ) ;
2007-03-11 17:14:52 +03:00
}
2008-06-03 10:52:30 +04:00
// NOTE we don't need to record the modifiers here, because they aren't visible from Java reflection
return typeBuilder . DefineTypeInitializer ( ) ;
2007-03-11 17:14:52 +03:00
}
2008-06-03 10:52:30 +04:00
// this finds the method that md is going to be overriding
private MethodWrapper FindBaseMethod ( string name , string sig , out bool explicitOverride )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
Debug . Assert ( ! classFile . IsInterface ) ;
Debug . Assert ( name ! = "<init>" ) ;
explicitOverride = false ;
TypeWrapper tw = wrapper . BaseTypeWrapper ;
while ( tw ! = null )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper baseMethod = tw . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod = = null )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
return null ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
// here are the complex rules for determining whether this method overrides the method we found
// RULE 1: final methods may not be overridden
// (note that we intentionally not check IsStatic here!)
if ( baseMethod . IsFinal
& & ! baseMethod . IsPrivate
& & ( baseMethod . IsPublic | | baseMethod . IsProtected | | baseMethod . DeclaringType . IsPackageAccessibleFrom ( wrapper ) ) )
{
throw new VerifyError ( "final method " + baseMethod . Name + baseMethod . Signature + " in " + baseMethod . DeclaringType . Name + " is overriden in " + wrapper . Name ) ;
}
// RULE 1a: static methods are ignored (other than the RULE 1 check)
if ( baseMethod . IsStatic )
{
}
// RULE 2: public & protected methods can be overridden (package methods are handled by RULE 4)
// (by public, protected & *package* methods [even if they are in a different package])
else if ( baseMethod . IsPublic | | baseMethod . IsProtected )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
// if we already encountered a package method, we cannot override the base method of
// that package method
if ( explicitOverride )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
explicitOverride = false ;
return null ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
return baseMethod ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
// RULE 3: private and static methods are ignored
else if ( ! baseMethod . IsPrivate )
{
// RULE 4: package methods can only be overridden in the same package
if ( baseMethod . DeclaringType . IsPackageAccessibleFrom ( wrapper )
2009-02-10 10:24:30 +03:00
| | ( baseMethod . IsInternal & & baseMethod . DeclaringType . InternalsVisibleTo ( wrapper ) ) )
2008-06-03 10:52:30 +04:00
{
return baseMethod ;
}
// since we encountered a method with the same name/signature that we aren't overriding,
// we need to specify an explicit override
// NOTE we only do this if baseMethod isn't private, because if it is, Reflection.Emit
// will complain about the explicit MethodOverride (possibly a bug)
explicitOverride = true ;
}
tw = baseMethod . DeclaringType . BaseTypeWrapper ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
return null ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
internal string GenerateUniqueMethodName ( string basename , MethodWrapper mw )
2007-02-19 14:31:38 +03:00
{
2008-06-03 10:52:30 +04:00
return GenerateUniqueMethodName ( basename , mw . ReturnTypeForDefineMethod , mw . GetParametersForDefineMethod ( ) ) ;
2007-02-19 14:31:38 +03:00
}
2008-06-03 10:52:30 +04:00
internal string GenerateUniqueMethodName ( string basename , Type returnType , Type [ ] parameterTypes )
2006-04-10 13:09:09 +04:00
{
2008-06-03 10:52:30 +04:00
string name = basename ;
string key = GenerateClashKey ( "method" , name , returnType , parameterTypes ) ;
UpdateClashTable ( ) ;
2008-08-15 16:01:06 +04:00
lock ( memberclashtable )
2006-04-10 13:09:09 +04:00
{
2008-06-03 10:52:30 +04:00
for ( int clashcount = 0 ; memberclashtable . ContainsKey ( key ) ; clashcount + + )
2006-04-10 13:09:09 +04:00
{
2008-06-03 10:52:30 +04:00
name = basename + "_" + clashcount ;
key = GenerateClashKey ( "method" , name , returnType , parameterTypes ) ;
2006-04-10 13:09:09 +04:00
}
2008-06-03 10:52:30 +04:00
memberclashtable . Add ( key , key ) ;
2006-04-10 13:09:09 +04:00
}
2008-06-03 10:52:30 +04:00
return name ;
2006-04-10 13:09:09 +04:00
}
2008-11-14 11:37:22 +03:00
private static MethodInfo GetBaseFinalizeMethod ( TypeWrapper wrapper )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
for ( ; ; )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// HACK we get called during method linking (which is probably a bad idea) and
// it is possible for the base type not to be finished yet, so we look at the
// private state of the unfinished base types to find the finalize method.
DynamicTypeWrapper dtw = wrapper as DynamicTypeWrapper ;
if ( dtw = = null )
{
break ;
}
MethodWrapper mw = dtw . GetMethodWrapper ( StringConstants . FINALIZE , StringConstants . SIG_VOID , false ) ;
if ( mw ! = null )
{
mw . Link ( ) ;
}
2008-11-14 11:37:22 +03:00
MethodInfo finalizeImpl = dtw . impl . GetFinalizeMethod ( ) ;
if ( finalizeImpl ! = null )
2008-06-03 10:52:30 +04:00
{
2008-11-14 11:37:22 +03:00
return finalizeImpl ;
2008-06-03 10:52:30 +04:00
}
wrapper = wrapper . BaseTypeWrapper ;
2005-11-01 17:01:42 +03:00
}
2008-11-14 11:37:22 +03:00
if ( wrapper = = CoreClasses . java . lang . Object . Wrapper | | wrapper = = CoreClasses . java . lang . Throwable . Wrapper )
{
return typeof ( object ) . GetMethod ( "Finalize" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
}
2008-06-03 10:52:30 +04:00
Type type = wrapper . TypeAsBaseType ;
MethodInfo baseFinalize = type . GetMethod ( "__<Finalize>" , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
if ( baseFinalize ! = null )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
return baseFinalize ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
while ( type ! = null )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
foreach ( MethodInfo m in type . GetMethods ( BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance | BindingFlags . DeclaredOnly ) )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
if ( m . Name = = "Finalize"
& & m . ReturnType = = typeof ( void )
& & m . GetParameters ( ) . Length = = 0 )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
if ( m . GetBaseDefinition ( ) . DeclaringType = = typeof ( object ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
return m ;
2005-10-01 15:16:11 +04:00
}
}
}
2008-06-03 10:52:30 +04:00
type = type . BaseType ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
return null ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
private MethodAttributes GetPropertyAccess ( MethodWrapper mw )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
string sig = mw . ReturnType . SigName ;
if ( sig = = "V" )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
sig = mw . GetParameters ( ) [ 0 ] . SigName ;
}
int access = - 1 ;
foreach ( ClassFile . Field field in classFile . Fields )
{
if ( field . IsProperty
& & field . IsStatic = = mw . IsStatic
& & field . Signature = = sig
& & ( field . PropertyGetter = = mw . Name | | field . PropertySetter = = mw . Name ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
int nacc ;
if ( field . IsPublic )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
nacc = 3 ;
2005-10-01 15:16:11 +04:00
}
2008-06-03 10:52:30 +04:00
else if ( field . IsProtected )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
nacc = 2 ;
}
else if ( field . IsPrivate )
{
nacc = 0 ;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
else
{
2008-06-03 10:52:30 +04:00
nacc = 1 ;
}
if ( nacc > access )
{
access = nacc ;
2005-11-01 17:01:42 +03:00
}
2005-10-01 15:16:11 +04:00
}
2008-06-03 10:52:30 +04:00
}
switch ( access )
{
case 0 :
return MethodAttributes . Private ;
case 1 :
return MethodAttributes . Assembly ;
case 2 :
return MethodAttributes . FamORAssem ;
case 3 :
return MethodAttributes . Public ;
default :
throw new InvalidOperationException ( ) ;
}
}
private MethodBase GenerateMethod ( int index , bool unloadableOverrideStub )
{
methods [ index ] . AssertLinked ( ) ;
Profiler . Enter ( "JavaTypeImpl.GenerateMethod" ) ;
try
{
if ( index > = classFile . Methods . Length )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
if ( methods [ index ] . IsMirandaMethod )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// We're a Miranda method
Debug . Assert ( baseMethods [ index ] . DeclaringType . IsInterface ) ;
string name = GenerateUniqueMethodName ( methods [ index ] . Name , baseMethods [ index ] ) ;
2008-12-01 08:21:05 +03:00
MethodBuilder mb = typeBuilder . DefineMethod ( name , MethodAttributes . HideBySig | MethodAttributes . NewSlot | MethodAttributes . Public | MethodAttributes . Virtual | MethodAttributes . Abstract | MethodAttributes . CheckAccessOnOverride , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
2008-06-03 10:52:30 +04:00
AttributeHelper . HideFromReflection ( mb ) ;
#if STATIC_COMPILER
if ( unloadableOverrideStub | | name ! = methods [ index ] . Name )
{
// instead of creating an override stub, we created the Miranda method with the proper signature and
// decorate it with a NameSigAttribute that contains the real signature
AttributeHelper . SetNameSig ( mb , methods [ index ] . Name , methods [ index ] . Signature ) ;
}
#endif // STATIC_COMPILER
// if we changed the name or if the interface method name is remapped, we need to add an explicit methodoverride.
if ( ! baseMethods [ index ] . IsDynamicOnly & & name ! = baseMethods [ index ] . RealName )
{
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) baseMethods [ index ] . GetMethod ( ) ) ;
}
return mb ;
}
else if ( methods [ index ] . IsAccessStub )
{
Debug . Assert ( ! baseMethods [ index ] . HasCallerID ) ;
MethodAttributes stubattribs = baseMethods [ index ] . IsPublic ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
stubattribs | = MethodAttributes . HideBySig ;
if ( baseMethods [ index ] . IsStatic )
{
stubattribs | = MethodAttributes . Static ;
}
else
{
stubattribs | = MethodAttributes . CheckAccessOnOverride | MethodAttributes . Virtual ;
if ( baseMethods [ index ] . IsAbstract & & wrapper . IsAbstract )
{
stubattribs | = MethodAttributes . Abstract ;
}
if ( baseMethods [ index ] . IsFinal )
{
// NOTE final methods still need to be virtual, because a subclass may need this method to
// implement an interface method
stubattribs | = MethodAttributes . Final | MethodAttributes . NewSlot ;
}
}
MethodBuilder mb = typeBuilder . DefineMethod ( methods [ index ] . Name , stubattribs , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
AttributeHelper . HideFromReflection ( mb ) ;
if ( ! baseMethods [ index ] . IsAbstract )
{
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
int argc = methods [ index ] . GetParametersForDefineMethod ( ) . Length + ( methods [ index ] . IsStatic ? 0 : 1 ) ;
for ( int i = 0 ; i < argc ; i + + )
{
ilgen . Emit ( OpCodes . Ldarg_S , ( byte ) i ) ;
}
baseMethods [ index ] . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
else if ( ! wrapper . IsAbstract )
{
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( mb ) , "java.lang.AbstractMethodError" , wrapper . Name + "." + methods [ index ] . Name + methods [ index ] . Signature ) ;
2008-06-03 10:52:30 +04:00
}
return mb ;
2005-11-01 17:01:42 +03:00
}
else
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
throw new InvalidOperationException ( ) ;
2005-10-01 15:16:11 +04:00
}
}
2008-06-03 10:52:30 +04:00
ClassFile . Method m = classFile . Methods [ index ] ;
MethodBase method ;
bool setNameSig = methods [ index ] . ReturnType . IsErasedOrBoxedPrimitiveOrRemapped ;
foreach ( TypeWrapper tw in methods [ index ] . GetParameters ( ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
setNameSig | = tw . IsErasedOrBoxedPrimitiveOrRemapped ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
bool setModifiers = false ;
if ( methods [ index ] . HasCallerID & & ( m . Modifiers & Modifiers . VarArgs ) ! = 0 )
2006-04-23 14:46:51 +04:00
{
2008-06-03 10:52:30 +04:00
// the implicit callerID parameter was added at the end so that means we shouldn't use ParamArrayAttribute,
// so we need to explicitly record that the method is varargs
setModifiers = true ;
2006-04-23 14:46:51 +04:00
}
2008-06-03 10:52:30 +04:00
MethodAttributes attribs = MethodAttributes . HideBySig ;
if ( m . IsNative )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
if ( wrapper . IsPInvokeMethod ( m ) )
{
// this doesn't appear to be necessary, but we use the flag in Finish to know
// that we shouldn't emit a method body
attribs | = MethodAttributes . PinvokeImpl ;
}
else
{
setModifiers = true ;
}
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
if ( methods [ index ] . IsPropertyAccessor )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = GetPropertyAccess ( methods [ index ] ) ;
attribs | = MethodAttributes . SpecialName ;
setModifiers = true ;
2006-12-28 10:46:21 +03:00
}
else
{
2008-06-03 10:52:30 +04:00
if ( m . IsPrivate )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Private ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else if ( m . IsProtected )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . FamORAssem ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else if ( m . IsPublic )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Public ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Assembly ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 10:52:30 +04:00
if ( ReferenceEquals ( m . Name , StringConstants . INIT ) )
2006-05-15 13:08:01 +04:00
{
2008-06-03 10:52:30 +04:00
Type [ ] [ ] modopt = null ;
if ( setNameSig )
2006-05-15 13:08:01 +04:00
{
2008-06-03 10:52:30 +04:00
// we add optional modifiers to make the signature unique
TypeWrapper [ ] parameters = methods [ index ] . GetParameters ( ) ;
modopt = new Type [ parameters . Length ] [ ] ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
if ( parameters [ i ] . IsGhostArray )
{
TypeWrapper elemTypeWrapper = parameters [ i ] ;
while ( elemTypeWrapper . IsArray )
{
elemTypeWrapper = elemTypeWrapper . ElementTypeWrapper ;
}
modopt [ i ] = new Type [ ] { elemTypeWrapper . TypeAsTBD } ;
}
else if ( parameters [ i ] . IsBoxedPrimitive )
{
modopt [ i ] = new Type [ ] { typeof ( object ) } ;
}
else if ( parameters [ i ] . IsRemapped & & parameters [ i ] is DotNetTypeWrapper )
{
modopt [ i ] = new Type [ ] { parameters [ i ] . TypeAsSignatureType } ;
}
else if ( parameters [ i ] . IsUnloadable )
{
modopt [ i ] = new Type [ ] { wrapper . classLoader . GetTypeWrapperFactory ( ) . DefineUnloadable ( parameters [ i ] . Name ) } ;
}
}
2006-05-15 13:08:01 +04:00
}
2008-06-03 10:52:30 +04:00
// strictfp is the only modifier that a constructor can have
if ( m . IsStrictfp )
{
setModifiers = true ;
}
2009-03-06 09:43:40 +03:00
method = typeBuilder . DefineConstructor ( attribs , CallingConventions . Standard , methods [ index ] . GetParametersForDefineMethod ( ) , null , modopt ) ;
( ( ConstructorBuilder ) method ) . SetImplementationFlags ( MethodImplAttributes . NoInlining ) ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else if ( m . IsClassInitializer )
2006-04-05 15:04:43 +04:00
{
2008-06-03 10:52:30 +04:00
method = DefineClassInitializer ( typeBuilder ) ;
2006-04-05 15:04:43 +04:00
}
2008-06-03 10:52:30 +04:00
else
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
if ( m . IsAbstract )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
// only if the classfile is abstract, we make the CLR method abstract, otherwise,
// we have to generate a method that throws an AbstractMethodError (because the JVM
// allows abstract methods in non-abstract classes)
if ( classFile . IsAbstract )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
if ( classFile . IsPublic & & ! classFile . IsFinal & & ! ( m . IsPublic | | m . IsProtected ) )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
setModifiers = true ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else
{
attribs | = MethodAttributes . Abstract ;
}
}
else
{
setModifiers = true ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 10:52:30 +04:00
if ( m . IsFinal )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
if ( ! m . IsStatic & & ! m . IsPrivate )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Final ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
else
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
setModifiers = true ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 10:52:30 +04:00
if ( m . IsStatic )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Static ;
if ( m . IsSynchronized )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
setModifiers = true ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 10:52:30 +04:00
else if ( ! m . IsPrivate )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Virtual | MethodAttributes . CheckAccessOnOverride ;
}
string name = m . Name ;
#if STATIC_COMPILER
if ( ( m . Modifiers & Modifiers . Bridge ) ! = 0 & & ( m . IsPublic | | m . IsProtected ) & & wrapper . IsPublic )
{
string sigbase = m . Signature . Substring ( 0 , m . Signature . LastIndexOf ( ')' ) + 1 ) ;
foreach ( MethodWrapper mw in methods )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( mw . Name = = m . Name & & mw . Signature . StartsWith ( sigbase ) & & mw . Signature ! = m . Signature )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// To prevent bridge methods with covariant return types from confusing
// other .NET compilers (like C#), we rename the bridge method.
name = "<bridge>" + name ;
setNameSig = true ;
break ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
}
}
#endif
// if a method is virtual, we need to find the method it overrides (if any), for several reasons:
// - if we're overriding a method that has a different name (e.g. some of the virtual methods
// in System.Object [Equals <-> equals]) we need to add an explicit MethodOverride
// - if one of the base classes has a similar method that is private (or package) that we aren't
// overriding, we need to specify an explicit MethodOverride
MethodWrapper baseMce = baseMethods [ index ] ;
bool explicitOverride = methods [ index ] . IsExplicitOverride ;
if ( ( attribs & MethodAttributes . Virtual ) ! = 0 & & ! classFile . IsInterface )
{
// make sure the base method is already defined
Debug . Assert ( baseMce = = null | | baseMce . GetMethod ( ) ! = null ) ;
if ( baseMce = = null | | baseMce . DeclaringType . IsInterface )
{
// we need to set NewSlot here, to prevent accidentally overriding methods
// (for example, if a Java class has a method "boolean Equals(object)", we don't want that method
// to override System.Object.Equals)
attribs | = MethodAttributes . NewSlot ;
}
else
{
// if we have a method overriding a more accessible method (the JVM allows this), we need to make the
// method more accessible, because otherwise the CLR will complain that we're reducing access
MethodBase baseMethod = baseMce . GetMethod ( ) ;
if ( ( baseMethod . IsPublic & & ! m . IsPublic ) | |
( ( baseMethod . IsFamily | | baseMethod . IsFamilyOrAssembly ) & & ! m . IsPublic & & ! m . IsProtected ) | |
( ! m . IsPublic & & ! m . IsProtected & & ! baseMce . DeclaringType . IsPackageAccessibleFrom ( wrapper ) ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
attribs & = ~ MethodAttributes . MemberAccessMask ;
attribs | = baseMethod . IsPublic ? MethodAttributes . Public : MethodAttributes . FamORAssem ;
setModifiers = true ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
}
}
MethodBuilder mb = null ;
#if STATIC_COMPILER
mb = wrapper . DefineGhostMethod ( name , attribs , methods [ index ] ) ;
#endif
if ( mb = = null )
{
bool needFinalize = false ;
bool needDispatch = false ;
MethodInfo baseFinalize = null ;
if ( baseMce ! = null & & ReferenceEquals ( m . Name , StringConstants . FINALIZE ) & & ReferenceEquals ( m . Signature , StringConstants . SIG_VOID ) )
{
2008-11-14 11:37:22 +03:00
baseFinalize = GetBaseFinalizeMethod ( wrapper . BaseTypeWrapper ) ;
if ( baseMce . DeclaringType = = CoreClasses . java . lang . Object . Wrapper )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// This type is the first type in the hierarchy to introduce a finalize method
// (other than the one in java.lang.Object obviously), so we need to override
// the real Finalize method and emit a dispatch call to our finalize method.
needFinalize = true ;
needDispatch = true ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
else if ( m . IsFinal )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// One of our base classes already has a finalize method, so we already are
// hooked into the real Finalize, but we need to override it again, to make it
// final (so that non-Java types cannot override it either).
needFinalize = true ;
needDispatch = false ;
// If the base class finalize was optimized away, we need a dispatch call after all.
if ( baseFinalize . DeclaringType = = typeof ( object ) )
{
needDispatch = true ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
else
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// One of our base classes already has a finalize method, but it may have been an empty
// method so that the hookup to the real Finalize was optimized away, we need to check
// for that.
if ( baseFinalize . DeclaringType = = typeof ( object ) )
{
needFinalize = true ;
needDispatch = true ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
if ( needFinalize & &
! m . IsAbstract & & ! m . IsNative & &
( ! m . IsFinal | | classFile . IsFinal ) & &
m . Instructions . Length > 0 & &
m . Instructions [ 0 ] . NormalizedOpCode = = NormalizedByteCode . __return )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// we've got an empty finalize method, so we don't need to override the real finalizer
// (not having a finalizer makes a huge perf difference)
needFinalize = false ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
}
if ( setNameSig | | memberclashtable ! = null )
{
// TODO we really should make sure that the name we generate doesn't already exist in a
// base class (not in the Java method namespace, but in the CLR method namespace)
name = GenerateUniqueMethodName ( name , methods [ index ] ) ;
if ( name ! = m . Name )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
setNameSig = true ;
2005-11-01 17:01:42 +03:00
}
}
2008-12-01 08:23:51 +03:00
bool needMethodImpl = baseMce ! = null & & ( setNameSig | | explicitOverride | | baseMce . RealName ! = name ) & & ! needFinalize ;
2008-06-03 10:52:30 +04:00
if ( unloadableOverrideStub | | needMethodImpl )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . NewSlot ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
mb = typeBuilder . DefineMethod ( name , attribs , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
if ( unloadableOverrideStub )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
GenerateUnloadableOverrideStub ( wrapper , typeBuilder , baseMce , mb , methods [ index ] . ReturnTypeForDefineMethod , methods [ index ] . GetParametersForDefineMethod ( ) ) ;
}
else if ( needMethodImpl )
{
// assert that the method we're overriding is in fact virtual and not final!
Debug . Assert ( baseMce . GetMethod ( ) . IsVirtual & & ! baseMce . GetMethod ( ) . IsFinal ) ;
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) baseMce . GetMethod ( ) ) ;
}
if ( ! m . IsStatic & & ! m . IsAbstract & & ! m . IsPrivate & & baseMce ! = null & & ! baseMce . DeclaringType . IsPackageAccessibleFrom ( wrapper ) )
{
// we may have to explicitly override another package accessible abstract method
TypeWrapper btw = baseMce . DeclaringType . BaseTypeWrapper ;
while ( btw ! = null )
2007-01-23 18:45:45 +03:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper bmw = btw . GetMethodWrapper ( m . Name , m . Signature , true ) ;
if ( bmw = = null )
{
break ;
}
if ( bmw . DeclaringType . IsPackageAccessibleFrom ( wrapper ) & & bmw . IsAbstract & & ! ( bmw . IsPublic | | bmw . IsProtected ) )
{
if ( bmw ! = baseMce )
{
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) bmw . GetMethod ( ) ) ;
}
break ;
}
btw = bmw . DeclaringType . BaseTypeWrapper ;
2007-01-23 18:45:45 +03:00
}
2006-12-28 10:46:21 +03:00
}
2008-06-03 10:52:30 +04:00
// if we're overriding java.lang.Object.finalize we need to emit a stub to override System.Object.Finalize,
// or if we're subclassing a non-Java class that has a Finalize method, we need a new Finalize override
if ( needFinalize )
{
2008-11-14 11:37:22 +03:00
string finalizeName = baseFinalize . Name ;
MethodWrapper mwClash = wrapper . GetMethodWrapper ( finalizeName , StringConstants . SIG_VOID , true ) ;
if ( mwClash ! = null & & mwClash . GetMethod ( ) ! = baseFinalize )
2008-06-03 10:52:30 +04:00
{
2008-11-14 11:37:22 +03:00
finalizeName = "__<Finalize>" ;
2008-06-03 10:52:30 +04:00
}
MethodAttributes attr = MethodAttributes . HideBySig | MethodAttributes . Virtual ;
// make sure we don't reduce accessibility
attr | = baseFinalize . IsPublic ? MethodAttributes . Public : MethodAttributes . Family ;
if ( m . IsFinal )
{
attr | = MethodAttributes . Final ;
}
finalizeMethod = typeBuilder . DefineMethod ( finalizeName , attr , CallingConventions . Standard , typeof ( void ) , Type . EmptyTypes ) ;
if ( finalizeName ! = baseFinalize . Name )
{
typeBuilder . DefineMethodOverride ( finalizeMethod , baseFinalize ) ;
}
AttributeHelper . HideFromJava ( finalizeMethod ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( finalizeMethod ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . SkipFinalizer ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel skip = ilgen . DefineLabel ( ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Brtrue_S , skip ) ;
if ( needDispatch )
{
ilgen . BeginExceptionBlock ( ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Callvirt , mb ) ;
ilgen . BeginCatchBlock ( typeof ( object ) ) ;
ilgen . EndExceptionBlock ( ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Call , baseFinalize ) ;
}
ilgen . MarkLabel ( skip ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
#if STATIC_COMPILER
if ( classFile . Methods [ index ] . AnnotationDefault ! = null )
{
CustomAttributeBuilder cab = new CustomAttributeBuilder ( StaticCompiler . GetType ( "IKVM.Attributes.AnnotationDefaultAttribute" ) . GetConstructor ( new Type [ ] { typeof ( object ) } ) , new object [ ] { classFile . Methods [ index ] . AnnotationDefault } ) ;
mb . SetCustomAttribute ( cab ) ;
}
#endif // STATIC_COMPILER
}
method = mb ;
2006-04-20 11:30:59 +04:00
}
2008-06-03 10:52:30 +04:00
string [ ] exceptions = m . ExceptionsAttribute ;
methods [ index ] . SetDeclaredExceptions ( exceptions ) ;
#if STATIC_COMPILER
AttributeHelper . SetThrowsAttribute ( method , exceptions ) ;
if ( setModifiers | | m . IsInternal | | ( m . Modifiers & ( Modifiers . Synthetic | Modifiers . Bridge ) ) ! = 0 )
2006-04-20 11:30:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( method is ConstructorBuilder )
{
AttributeHelper . SetModifiers ( ( ConstructorBuilder ) method , m . Modifiers , m . IsInternal ) ;
}
else
{
AttributeHelper . SetModifiers ( ( MethodBuilder ) method , m . Modifiers , m . IsInternal ) ;
}
2006-04-20 11:30:59 +04:00
}
2008-06-03 10:52:30 +04:00
if ( ( m . Modifiers & ( Modifiers . Synthetic | Modifiers . Bridge ) ) ! = 0
2008-09-21 13:50:41 +04:00
& & ( m . IsPublic | | m . IsProtected )
& & wrapper . IsPublic
& & ! IsAccessBridge ( classFile , m ) )
2006-04-20 11:30:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( method is ConstructorBuilder )
{
AttributeHelper . SetEditorBrowsableNever ( ( ConstructorBuilder ) method ) ;
}
else
{
AttributeHelper . SetEditorBrowsableNever ( ( MethodBuilder ) method ) ;
}
// TODO on WHIDBEY apply CompilerGeneratedAttribute
2006-04-20 11:30:59 +04:00
}
2008-06-03 10:52:30 +04:00
if ( m . DeprecatedAttribute )
2006-04-20 11:30:59 +04:00
{
2008-06-03 10:52:30 +04:00
AttributeHelper . SetDeprecatedAttribute ( method ) ;
2006-04-20 11:30:59 +04:00
}
2008-06-03 10:52:30 +04:00
if ( setNameSig )
2006-06-20 18:31:56 +04:00
{
2008-06-03 10:52:30 +04:00
AttributeHelper . SetNameSig ( method , m . Name , m . Signature ) ;
}
if ( m . GenericSignature ! = null )
{
AttributeHelper . SetSignatureAttribute ( method , m . GenericSignature ) ;
}
#else // STATIC_COMPILER
if ( setModifiers )
{
// shut up the compiler
2006-06-20 18:31:56 +04:00
}
2008-06-03 10:52:30 +04:00
#endif // STATIC_COMPILER
return method ;
}
finally
{
Profiler . Leave ( "JavaTypeImpl.GenerateMethod" ) ;
2006-06-20 18:31:56 +04:00
}
2008-06-03 10:52:30 +04:00
}
2008-04-14 09:13:41 +04:00
2008-09-21 13:50:41 +04:00
#if STATIC_COMPILER
// The classic example of an access bridge is StringBuilder.length(), the JDK 6 compiler
// generates this to work around a reflection problem (which otherwise wouldn't surface the
// length() method, because it is defined in the non-public base class AbstractStringBuilder.)
private static bool IsAccessBridge ( ClassFile classFile , ClassFile . Method m )
{
// HACK this is a pretty gross hack
// We look at the method body to figure out if the bridge method calls another method with the exact
// same name/signature and if that is the case, we assume that it is an access bridge.
// This code is based on the javac algorithm in addBridgeIfNeeded(...) in com/sun/tools/javac/comp/TransTypes.java.
if ( ( m . Modifiers & ( Modifiers . Abstract | Modifiers . Native | Modifiers . Public | Modifiers . Bridge ) ) = = ( Modifiers . Public | Modifiers . Bridge ) )
{
foreach ( ClassFile . Method . Instruction instr in m . Instructions )
{
if ( instr . NormalizedOpCode = = NormalizedByteCode . __invokespecial )
{
ClassFile . ConstantPoolItemMI cpi = classFile . SafeGetMethodref ( instr . Arg1 ) ;
return cpi ! = null & & cpi . Name = = m . Name & & cpi . Signature = = m . Signature ;
}
}
}
return false ;
}
#endif // STATIC_COMPILER
2008-06-03 10:52:30 +04:00
internal static void GenerateUnloadableOverrideStub ( DynamicTypeWrapper wrapper , TypeBuilder typeBuilder , MethodWrapper baseMethod , MethodInfo target , Type targetRet , Type [ ] targetArgs )
{
Debug . Assert ( ! baseMethod . HasCallerID ) ;
Type stubret = baseMethod . ReturnTypeForDefineMethod ;
Type [ ] stubargs = baseMethod . GetParametersForDefineMethod ( ) ;
string name = wrapper . GenerateUniqueMethodName ( baseMethod . RealName + "/unloadablestub" , baseMethod ) ;
MethodBuilder overrideStub = typeBuilder . DefineMethod ( name , MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . NewSlot | MethodAttributes . Final , stubret , stubargs ) ;
AttributeHelper . HideFromJava ( overrideStub ) ;
typeBuilder . DefineMethodOverride ( overrideStub , ( MethodInfo ) baseMethod . GetMethod ( ) ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( overrideStub ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
for ( int i = 0 ; i < targetArgs . Length ; i + + )
2008-04-14 09:13:41 +04:00
{
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_S , ( byte ) ( i + 1 ) ) ;
if ( targetArgs [ i ] ! = stubargs [ i ] )
2008-04-14 09:13:41 +04:00
{
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Castclass , targetArgs [ i ] ) ;
2008-04-14 09:13:41 +04:00
}
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Callvirt , target ) ;
if ( targetRet ! = stubret )
{
ilgen . Emit ( OpCodes . Castclass , stubret ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
2002-12-18 19:00:25 +03:00
}
2003-12-24 14:51:41 +03:00
2008-06-03 10:52:30 +04:00
internal override Type Type
2004-09-05 13:37:58 +04:00
{
2008-06-03 10:52:30 +04:00
get
2003-08-13 19:00:41 +04:00
{
2008-06-03 10:52:30 +04:00
return typeBuilder ;
2003-08-13 19:00:41 +04:00
}
2008-06-03 10:52:30 +04:00
}
internal override string GetGenericSignature ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericMethodSignature ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericFieldSignature ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2003-05-30 16:08:59 +04:00
2008-06-03 10:52:30 +04:00
internal override object [ ] GetDeclaredAnnotations ( )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object GetMethodDefaultValue ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] GetMethodAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] [ ] GetParameterAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] GetFieldAnnotations ( int index )
{
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2008-11-14 11:37:22 +03:00
internal override MethodInfo GetFinalizeMethod ( )
{
return finalizeMethod ;
}
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
internal override Annotation Annotation
{
get
2004-09-05 13:37:58 +04:00
{
2008-06-03 10:52:30 +04:00
return annotationBuilder ;
2005-06-01 13:49:30 +04:00
}
}
2008-06-03 10:52:30 +04:00
internal override Type EnumType
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
get
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
return enumBuilder ;
}
}
#endif // STATIC_COMPILER
}
2004-09-17 13:32:06 +04:00
2008-06-03 10:52:30 +04:00
private sealed class Metadata
{
private string [ ] genericMetaData ;
private object [ ] [ ] annotations ;
2004-09-17 13:32:06 +04:00
2008-06-03 10:52:30 +04:00
private Metadata ( string [ ] genericMetaData , object [ ] [ ] annotations )
{
this . genericMetaData = genericMetaData ;
this . annotations = annotations ;
}
internal static Metadata Create ( ClassFile classFile )
{
if ( classFile . MajorVersion < 49 )
{
return null ;
}
string [ ] genericMetaData = null ;
object [ ] [ ] annotations = null ;
for ( int i = 0 ; i < classFile . Methods . Length ; i + + )
{
if ( classFile . Methods [ i ] . GenericSignature ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
}
genericMetaData [ i + 4 ] = classFile . Methods [ i ] . GenericSignature ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . Methods [ i ] . Annotations ! = null )
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( annotations = = null )
2005-02-02 18:11:26 +03:00
{
2008-06-03 10:52:30 +04:00
annotations = new object [ 5 ] [ ] ;
2005-02-02 18:11:26 +03:00
}
2008-06-03 10:52:30 +04:00
if ( annotations [ 1 ] = = null )
2005-02-02 18:11:26 +03:00
{
2008-06-03 10:52:30 +04:00
annotations [ 1 ] = new object [ classFile . Methods . Length ] ;
2005-02-02 18:11:26 +03:00
}
2008-06-03 10:52:30 +04:00
annotations [ 1 ] [ i ] = classFile . Methods [ i ] . Annotations ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . Methods [ i ] . ParameterAnnotations ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 2 ] = = null )
{
annotations [ 2 ] = new object [ classFile . Methods . Length ] ;
}
annotations [ 2 ] [ i ] = classFile . Methods [ i ] . ParameterAnnotations ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . Methods [ i ] . AnnotationDefault ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
if ( annotations = = null )
{
annotations = new object [ 5 ] [ ] ;
}
if ( annotations [ 3 ] = = null )
{
annotations [ 3 ] = new object [ classFile . Methods . Length ] ;
}
annotations [ 3 ] [ i ] = classFile . Methods [ i ] . AnnotationDefault ;
2003-05-30 16:08:59 +04:00
}
2008-06-03 10:52:30 +04:00
}
for ( int i = 0 ; i < classFile . Fields . Length ; i + + )
{
if ( classFile . Fields [ i ] . GenericSignature ! = null )
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( genericMetaData = = null )
{
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
}
genericMetaData [ i + 4 + classFile . Methods . Length ] = classFile . Fields [ i ] . GenericSignature ;
2003-05-30 16:08:59 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . Fields [ i ] . Annotations ! = null )
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( annotations = = null )
2005-02-02 18:11:26 +03:00
{
2008-06-03 10:52:30 +04:00
annotations = new object [ 5 ] [ ] ;
2003-08-01 16:12:08 +04:00
}
2008-06-03 10:52:30 +04:00
if ( annotations [ 4 ] = = null )
{
annotations [ 4 ] = new object [ classFile . Fields . Length ] [ ] ;
}
annotations [ 4 ] [ i ] = classFile . Fields [ i ] . Annotations ;
2003-05-30 16:08:59 +04:00
}
2008-06-03 10:52:30 +04:00
}
if ( classFile . EnclosingMethod ! = null )
{
if ( genericMetaData = = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
}
genericMetaData [ 0 ] = classFile . EnclosingMethod [ 0 ] ;
genericMetaData [ 1 ] = classFile . EnclosingMethod [ 1 ] ;
genericMetaData [ 2 ] = classFile . EnclosingMethod [ 2 ] ;
}
if ( classFile . GenericSignature ! = null )
{
if ( genericMetaData = = null )
{
genericMetaData = new string [ classFile . Methods . Length + classFile . Fields . Length + 4 ] ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
genericMetaData [ 3 ] = classFile . GenericSignature ;
}
if ( classFile . Annotations ! = null )
{
if ( annotations = = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
annotations = new object [ 5 ] [ ] ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
annotations [ 0 ] = classFile . Annotations ;
}
if ( genericMetaData ! = null | | annotations ! = null )
{
return new Metadata ( genericMetaData , annotations ) ;
}
return null ;
}
internal static string GetGenericSignature ( Metadata m )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ 3 ] ;
}
return null ;
}
internal static string [ ] GetEnclosingMethod ( Metadata m )
{
if ( m ! = null & & m . genericMetaData ! = null & & m . genericMetaData [ 0 ] ! = null )
{
return new string [ ] { m . genericMetaData [ 0 ] , m . genericMetaData [ 1 ] , m . genericMetaData [ 2 ] } ;
}
return null ;
}
internal static string GetGenericMethodSignature ( Metadata m , int index )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ index + 4 ] ;
}
return null ;
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal static string GetGenericFieldSignature ( Metadata m , int index )
{
if ( m ! = null & & m . genericMetaData ! = null )
{
return m . genericMetaData [ index + 4 ] ;
}
return null ;
}
internal static object [ ] GetAnnotations ( Metadata m )
{
if ( m ! = null & & m . annotations ! = null )
{
return m . annotations [ 0 ] ;
}
return null ;
}
internal static object [ ] GetMethodAnnotations ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 1 ] ! = null )
{
return ( object [ ] ) m . annotations [ 1 ] [ index ] ;
}
return null ;
}
internal static object [ ] [ ] GetMethodParameterAnnotations ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 2 ] ! = null )
{
return ( object [ ] [ ] ) m . annotations [ 2 ] [ index ] ;
}
return null ;
}
internal static object GetMethodDefaultValue ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 3 ] ! = null )
{
return m . annotations [ 3 ] [ index ] ;
}
return null ;
}
// note that unlike GetGenericFieldSignature, the index is simply the field index
internal static object [ ] GetFieldAnnotations ( Metadata m , int index )
{
if ( m ! = null & & m . annotations ! = null & & m . annotations [ 4 ] ! = null )
{
return ( object [ ] ) m . annotations [ 4 ] [ index ] ;
2004-09-27 14:17:34 +04:00
}
2008-06-03 10:52:30 +04:00
return null ;
}
}
private sealed class FinishedTypeImpl : DynamicImpl
{
private Type type ;
private TypeWrapper [ ] innerclasses ;
private TypeWrapper declaringTypeWrapper ;
private Modifiers reflectiveModifiers ;
private MethodInfo clinitMethod ;
2008-11-14 11:37:22 +03:00
private MethodInfo finalizeMethod ;
2008-06-03 10:52:30 +04:00
private Metadata metadata ;
#if STATIC_COMPILER
private Annotation annotationBuilder ;
private TypeBuilder enumBuilder ;
#endif
2008-11-14 11:37:22 +03:00
internal FinishedTypeImpl ( Type type , TypeWrapper [ ] innerclasses , TypeWrapper declaringTypeWrapper , Modifiers reflectiveModifiers , Metadata metadata , MethodInfo clinitMethod , MethodInfo finalizeMethod
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
, Annotation annotationBuilder
, TypeBuilder enumBuilder
#endif
)
{
this . type = type ;
this . innerclasses = innerclasses ;
this . declaringTypeWrapper = declaringTypeWrapper ;
this . reflectiveModifiers = reflectiveModifiers ;
2008-11-14 11:37:22 +03:00
this . clinitMethod = clinitMethod ;
this . finalizeMethod = finalizeMethod ;
2008-06-03 10:52:30 +04:00
this . metadata = metadata ;
#if STATIC_COMPILER
this . annotationBuilder = annotationBuilder ;
this . enumBuilder = enumBuilder ;
#endif
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
2008-06-03 10:52:30 +04:00
// TODO compute the innerclasses lazily (and fix JavaTypeImpl to not always compute them)
return innerclasses ;
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
2008-06-03 10:52:30 +04:00
// TODO compute lazily (and fix JavaTypeImpl to not always compute it)
return declaringTypeWrapper ;
2005-06-01 13:49:30 +04:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
return reflectiveModifiers ;
2004-08-17 13:05:21 +04:00
}
2003-02-18 12:30:34 +03:00
}
2008-06-03 10:52:30 +04:00
internal override Type Type
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
return type ;
2004-08-17 13:05:21 +04:00
}
}
2008-06-03 16:10:07 +04:00
internal override void EmitRunClassConstructor ( CodeEmitter ilgen )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
if ( clinitMethod ! = null )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
2004-08-17 13:05:21 +04:00
}
}
2008-06-03 10:52:30 +04:00
internal override DynamicImpl Finish ( )
{
return this ;
}
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
// we should never be called, because all methods on a finished type are already linked
Debug . Assert ( false ) ;
return mw . GetMethod ( ) ;
}
internal override FieldInfo LinkField ( FieldWrapper fw )
{
// we should never be called, because all fields on a finished type are already linked
Debug . Assert ( false ) ;
return fw . GetField ( ) ;
}
internal override string GetGenericSignature ( )
{
return Metadata . GetGenericSignature ( metadata ) ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return Metadata . GetEnclosingMethod ( metadata ) ;
}
internal override string GetGenericMethodSignature ( int index )
{
return Metadata . GetGenericMethodSignature ( metadata , index ) ;
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal override string GetGenericFieldSignature ( int index )
{
return Metadata . GetGenericFieldSignature ( metadata , index ) ;
}
internal override object [ ] GetDeclaredAnnotations ( )
{
return Metadata . GetAnnotations ( metadata ) ;
}
internal override object GetMethodDefaultValue ( int index )
{
return Metadata . GetMethodDefaultValue ( metadata , index ) ;
}
internal override object [ ] GetMethodAnnotations ( int index )
{
return Metadata . GetMethodAnnotations ( metadata , index ) ;
}
internal override object [ ] [ ] GetParameterAnnotations ( int index )
{
return Metadata . GetMethodParameterAnnotations ( metadata , index ) ;
}
internal override object [ ] GetFieldAnnotations ( int index )
{
return Metadata . GetFieldAnnotations ( metadata , index ) ;
}
2008-11-14 11:37:22 +03:00
internal override MethodInfo GetFinalizeMethod ( )
{
return finalizeMethod ;
}
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
internal override Annotation Annotation
2002-12-29 19:27:00 +03:00
{
2008-06-03 10:52:30 +04:00
get
2008-04-01 21:39:07 +04:00
{
2008-06-03 10:52:30 +04:00
return annotationBuilder ;
2008-04-01 21:39:07 +04:00
}
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
internal override Type EnumType
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2008-06-03 10:52:30 +04:00
return enumBuilder ;
2005-05-31 12:57:24 +04:00
}
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
#endif // STATIC_COMPILER
}
2005-06-01 13:49:30 +04:00
2008-06-03 10:52:30 +04:00
internal sealed class FinishContext
{
private readonly ClassFile classFile ;
private readonly DynamicTypeWrapper wrapper ;
private readonly TypeBuilder typeBuilder ;
private FieldInfo classObjectField ;
private TypeBuilder typeCallerID ;
private FieldInfo callerIDField ;
private List < System . Threading . ThreadStart > postFinishProcs ;
internal FinishContext ( ClassFile classFile , DynamicTypeWrapper wrapper , TypeBuilder typeBuilder )
2006-08-15 12:50:43 +04:00
{
2008-06-03 10:52:30 +04:00
this . classFile = classFile ;
this . wrapper = wrapper ;
this . typeBuilder = typeBuilder ;
2006-08-15 12:50:43 +04:00
}
2008-06-03 10:52:30 +04:00
internal FieldInfo ClassObjectField
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
get
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( classObjectField = = null )
2005-06-01 13:49:30 +04:00
{
2009-03-04 08:47:18 +03:00
classObjectField = RuntimeHelperTypes . GetClassLiteralField ( typeBuilder ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
return classObjectField ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
internal FieldInfo CallerIDField
2006-07-24 15:47:55 +04:00
{
2008-06-03 10:52:30 +04:00
get
2006-07-24 15:47:55 +04:00
{
2008-06-03 10:52:30 +04:00
if ( callerIDField = = null )
2006-07-24 15:47:55 +04:00
{
2008-06-03 10:52:30 +04:00
TypeWrapper tw = CoreClasses . ikvm . @internal . CallerID . Wrapper ;
callerIDField = typeBuilder . DefineField ( "__<callerID>" , tw . TypeAsSignatureType , FieldAttributes . Private | FieldAttributes . Static | FieldAttributes . InitOnly | FieldAttributes . SpecialName ) ;
2006-07-24 15:47:55 +04:00
}
2008-06-03 10:52:30 +04:00
return callerIDField ;
2006-07-24 15:47:55 +04:00
}
}
2008-06-03 10:52:30 +04:00
internal void RegisterPostFinishProc ( System . Threading . ThreadStart proc )
2008-04-14 09:13:41 +04:00
{
2008-06-03 10:52:30 +04:00
if ( postFinishProcs = = null )
2008-04-14 09:13:41 +04:00
{
2008-06-03 10:52:30 +04:00
postFinishProcs = new List < System . Threading . ThreadStart > ( ) ;
2008-04-14 09:13:41 +04:00
}
2008-06-03 10:52:30 +04:00
postFinishProcs . Add ( proc ) ;
2008-04-14 09:13:41 +04:00
}
2008-06-03 10:52:30 +04:00
internal Type FinishImpl ( )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper [ ] methods = wrapper . GetMethods ( ) ;
FieldWrapper [ ] fields = wrapper . GetFields ( ) ;
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
2008-06-03 10:52:30 +04:00
wrapper . FinishGhost ( typeBuilder , methods ) ;
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2008-06-03 10:52:30 +04:00
// if we're not abstract make sure we don't inherit any abstract methods
if ( ! wrapper . IsAbstract )
{
TypeWrapper parent = wrapper . BaseTypeWrapper ;
// if parent is not abstract, the .NET implementation will never have abstract methods (only
// stubs that throw AbstractMethodError)
// NOTE interfaces are supposed to be abstract, but the VM doesn't enforce this, so
// we have to check for a null parent (interfaces have no parent).
while ( parent ! = null & & parent . IsAbstract )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( MethodWrapper mw in parent . GetMethods ( ) )
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
MethodInfo mi = mw . GetMethod ( ) as MethodInfo ;
if ( mi ! = null & & mi . IsAbstract & & ! mi . DeclaringType . IsInterface )
2008-03-04 10:28:00 +03:00
{
2008-06-03 10:52:30 +04:00
bool needStub = false ;
bool needRename = false ;
if ( mw . IsPublic | | mw . IsProtected )
2008-03-04 10:28:00 +03:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper fmw = wrapper . GetMethodWrapper ( mw . Name , mw . Signature , true ) ;
while ( fmw ! = mw & & ( fmw . IsStatic | | fmw . IsPrivate ) )
2008-03-04 10:28:00 +03:00
{
2008-06-03 10:52:30 +04:00
needRename = true ;
fmw = fmw . DeclaringType . BaseTypeWrapper . GetMethodWrapper ( mw . Name , mw . Signature , true ) ;
}
if ( fmw = = mw & & fmw . DeclaringType ! = wrapper )
{
needStub = true ;
2008-03-04 10:28:00 +03:00
}
}
2008-06-03 10:52:30 +04:00
else
2008-03-04 10:28:00 +03:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper fmw = wrapper . GetMethodWrapper ( mw . Name , mw . Signature , true ) ;
while ( fmw ! = mw & & ( fmw . IsStatic | | fmw . IsPrivate | | ! fmw . DeclaringType . IsPackageAccessibleFrom ( mw . DeclaringType ) ) )
{
needRename = true ;
fmw = fmw . DeclaringType . BaseTypeWrapper . GetMethodWrapper ( mw . Name , mw . Signature , true ) ;
}
if ( fmw = = mw & & fmw . DeclaringType ! = wrapper )
{
needStub = true ;
}
2008-03-04 10:28:00 +03:00
}
2008-06-03 10:52:30 +04:00
if ( needStub )
2008-03-04 10:28:00 +03:00
{
2008-06-03 10:52:30 +04:00
// NOTE in Sun's JRE 1.4.1 this method cannot be overridden by subclasses,
// but I think this is a bug, so we'll support it anyway.
string name = mi . Name ;
MethodAttributes attr = mi . Attributes & ~ ( MethodAttributes . Abstract | MethodAttributes . NewSlot ) ;
if ( needRename )
{
name = "__<>" + name + "/" + mi . DeclaringType . FullName ;
attr = MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . NewSlot ;
}
MethodBuilder mb = typeBuilder . DefineMethod ( name , attr , CallingConventions . Standard , mw . ReturnTypeForDefineMethod , mw . GetParametersForDefineMethod ( ) ) ;
if ( needRename )
{
typeBuilder . DefineMethodOverride ( mb , mi ) ;
}
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( mb ) , "java.lang.AbstractMethodError" , mw . DeclaringType . Name + "." + mw . Name + mw . Signature ) ;
2008-03-04 10:28:00 +03:00
}
}
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
parent = parent . BaseTypeWrapper ;
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
}
2008-08-15 16:01:06 +04:00
Dictionary < MethodKey , MethodInfo > invokespecialstubcache = new Dictionary < MethodKey , MethodInfo > ( ) ;
2008-06-03 10:52:30 +04:00
bool basehasclinit = wrapper . BaseTypeWrapper ! = null & & wrapper . BaseTypeWrapper . HasStaticInitializer ;
int clinitIndex = - 1 ;
bool hasConstructor = false ;
for ( int i = 0 ; i < classFile . Methods . Length ; i + + )
{
ClassFile . Method m = classFile . Methods [ i ] ;
MethodBase mb = methods [ i ] . GetMethod ( ) ;
2009-03-06 09:43:40 +03:00
if ( mb = = null )
{
// method doesn't really exist (e.g. delegate constructor)
if ( m . Name = = StringConstants . INIT )
{
hasConstructor = true ;
}
}
else if ( mb is ConstructorBuilder )
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( m . IsClassInitializer )
{
// we handle the <clinit> after we've done the other methods,
// to make it easier to inject code needed by the other methods
clinitIndex = i ;
continue ;
}
else
{
hasConstructor = true ;
}
2009-03-06 09:43:40 +03:00
CodeEmitter ilGenerator = CodeEmitter . Create ( ( ConstructorBuilder ) mb ) ;
CompileConstructorBody ( this , ilGenerator , i , invokespecialstubcache ) ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-05-30 16:08:59 +04:00
{
2008-06-03 10:52:30 +04:00
if ( m . IsAbstract )
2002-12-18 19:00:25 +03:00
{
2008-06-03 10:52:30 +04:00
bool stub = false ;
if ( ! classFile . IsAbstract )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
// NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but
// the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError
stub = true ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
else if ( classFile . IsPublic & & ! classFile . IsFinal & & ! ( m . IsPublic | | m . IsProtected ) )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
// We have an abstract package accessible method in our public class. To allow a class in another
// assembly to subclass this class, we must fake the abstractness of this method.
stub = true ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( stub )
2002-12-18 19:00:25 +03:00
{
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( ( MethodBuilder ) mb ) ;
2008-06-03 10:52:30 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
EmitHelper . Throw ( ilGenerator , "java.lang.AbstractMethodError" , classFile . Name + "." + m . Name + m . Signature ) ;
2002-12-18 19:00:25 +03:00
}
}
2008-06-03 10:52:30 +04:00
else if ( m . IsNative )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
if ( ( mb . Attributes & MethodAttributes . PinvokeImpl ) ! = 0 )
2005-09-08 21:44:35 +04:00
{
2008-06-03 10:52:30 +04:00
continue ;
2005-09-08 21:44:35 +04:00
}
2009-03-06 08:33:08 +03:00
if ( wrapper . IsDelegate )
{
( ( MethodBuilder ) mb ) . SetImplementationFlags ( mb . GetMethodImplementationFlags ( ) | MethodImplAttributes . Runtime ) ;
continue ;
}
2008-06-03 10:52:30 +04:00
Profiler . Enter ( "JavaTypeImpl.Finish.Native" ) ;
try
2007-02-01 15:41:22 +03:00
{
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( ( MethodBuilder ) mb ) ;
2008-06-03 10:52:30 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
#if STATIC_COMPILER
// do we have a native implementation in map.xml?
if ( wrapper . EmitMapXmlMethodBody ( ilGenerator , classFile , m ) )
2007-02-01 15:41:22 +03:00
{
2008-06-03 10:52:30 +04:00
continue ;
2007-02-01 15:41:22 +03:00
}
#endif
2008-06-03 10:52:30 +04:00
// see if there exists a IKVM.NativeCode class for this type
Type nativeCodeType = null ;
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
2008-06-03 10:52:30 +04:00
nativeCodeType = StaticCompiler . GetType ( "IKVM.NativeCode." + classFile . Name . Replace ( '$' , '+' ) , false ) ;
2006-09-12 13:57:36 +04:00
#endif
2008-06-03 10:52:30 +04:00
MethodInfo nativeMethod = null ;
TypeWrapper [ ] args = methods [ i ] . GetParameters ( ) ;
if ( nativeCodeType ! = null )
2004-12-02 11:43:05 +03:00
{
2008-06-03 10:52:30 +04:00
TypeWrapper [ ] nargs = args ;
if ( ! m . IsStatic )
{
nargs = new TypeWrapper [ args . Length + 1 ] ;
args . CopyTo ( nargs , 1 ) ;
nargs [ 0 ] = this . wrapper ;
}
MethodInfo [ ] nativeCodeTypeMethods = nativeCodeType . GetMethods ( BindingFlags . Static | BindingFlags . Public ) ;
foreach ( MethodInfo method in nativeCodeTypeMethods )
{
ParameterInfo [ ] param = method . GetParameters ( ) ;
TypeWrapper [ ] match = new TypeWrapper [ param . Length ] ;
for ( int j = 0 ; j < param . Length ; j + + )
{
match [ j ] = ClassLoaderWrapper . GetWrapperFromType ( param [ j ] . ParameterType ) ;
}
if ( m . Name = = method . Name & & IsCompatibleArgList ( nargs , match ) )
{
// TODO instead of taking the first matching method, we should find the best one
nativeMethod = method ;
break ;
}
}
2004-12-02 11:43:05 +03:00
}
2008-06-03 10:52:30 +04:00
if ( nativeMethod ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
int add = 0 ;
if ( ! m . IsStatic )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
add = 1 ;
}
for ( int j = 0 ; j < args . Length ; j + + )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , nativeMethod ) ;
TypeWrapper retTypeWrapper = methods [ i ] . ReturnType ;
if ( ! retTypeWrapper . TypeAsTBD . Equals ( nativeMethod . ReturnType ) & & ! retTypeWrapper . IsGhost )
{
ilGenerator . Emit ( OpCodes . Castclass , retTypeWrapper . TypeAsTBD ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ret ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2008-06-03 10:52:30 +04:00
if ( wrapper . classLoader . NoJNI )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
// since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch
Tracer . Warning ( Tracer . Compiler , "Native method not implemented: {0}.{1}.{2}" , classFile . Name , m . Name , m . Signature ) ;
EmitHelper . Throw ( ilGenerator , "java.lang.UnsatisfiedLinkError" , "Native method not implemented (compiled with -nojni): " + classFile . Name + "." + m . Name + m . Signature ) ;
}
else
{
if ( JVM . IsSaveDebugImage )
{
#if ! STATIC_COMPILER
JniProxyBuilder . Generate ( this , ilGenerator , wrapper , methods [ i ] , typeBuilder , classFile , m , args ) ;
#endif // !STATIC_COMPILER
}
else
{
JniBuilder . Generate ( this , ilGenerator , wrapper , methods [ i ] , typeBuilder , classFile , m , args , false ) ;
}
2005-06-01 13:49:30 +04:00
}
}
2004-12-02 11:43:05 +03:00
}
2008-06-03 10:52:30 +04:00
finally
2004-03-16 20:10:09 +03:00
{
2008-06-03 10:52:30 +04:00
Profiler . Leave ( "JavaTypeImpl.Finish.Native" ) ;
2004-03-16 20:10:09 +03:00
}
2008-06-03 10:52:30 +04:00
}
else
{
MethodBuilder mbld = ( MethodBuilder ) mb ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( mbld ) ;
2008-06-03 10:52:30 +04:00
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
#if STATIC_COMPILER
if ( wrapper . EmitMapXmlMethodBody ( ilGenerator , classFile , m ) )
2005-08-05 12:40:54 +04:00
{
2008-06-03 10:52:30 +04:00
continue ;
2005-08-05 12:40:54 +04:00
}
2008-06-03 10:52:30 +04:00
#endif // STATIC_COMPILER
LineNumberTableAttribute . LineNumberWriter lineNumberTable = null ;
bool nonleaf = false ;
Compiler . Compile ( this , wrapper , methods [ i ] , classFile , m , ilGenerator , ref nonleaf , invokespecialstubcache , ref lineNumberTable ) ;
2009-04-06 14:10:17 +04:00
ilGenerator . CheckLabels ( ) ;
2008-06-03 10:52:30 +04:00
if ( nonleaf )
2004-03-16 20:10:09 +03:00
{
2008-06-03 10:52:30 +04:00
mbld . SetImplementationFlags ( mbld . GetMethodImplementationFlags ( ) | MethodImplAttributes . NoInlining ) ;
2004-03-16 20:10:09 +03:00
}
2008-06-03 10:52:30 +04:00
if ( lineNumberTable ! = null )
2004-03-16 20:10:09 +03:00
{
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
AttributeHelper . SetLineNumberTable ( methods [ i ] . GetMethod ( ) , lineNumberTable ) ;
#else // STATIC_COMPILER
if ( wrapper . lineNumberTables = = null )
{
wrapper . lineNumberTables = new byte [ methods . Length ] [ ] ;
}
wrapper . lineNumberTables [ i ] = lineNumberTable . ToArray ( ) ;
#endif // STATIC_COMPILER
2004-03-16 20:10:09 +03:00
}
2008-06-03 10:52:30 +04:00
}
}
}
if ( clinitIndex ! = - 1 | | ( basehasclinit & & ! classFile . IsInterface ) | | classFile . HasInitializedFields | | callerIDField ! = null )
{
ConstructorBuilder cb ;
if ( clinitIndex ! = - 1 )
{
cb = ( ConstructorBuilder ) methods [ clinitIndex ] . GetMethod ( ) ;
}
else
{
cb = JavaTypeImpl . DefineClassInitializer ( typeBuilder ) ;
AttributeHelper . HideFromJava ( cb ) ;
}
2008-06-03 16:10:07 +04:00
CodeEmitter ilGenerator = CodeEmitter . Create ( cb ) ;
2008-06-03 10:52:30 +04:00
// HACK we start out by emitting the users code, because that may trigger the creation of caller id infrastructure
2008-06-03 16:10:07 +04:00
CodeEmitterLabel label1 = null ;
2008-06-03 10:52:30 +04:00
if ( clinitIndex ! = - 1 )
{
label1 = ilGenerator . DefineLabel ( ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel label2 = ilGenerator . DefineLabel ( ) ;
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Br , label2 ) ;
ilGenerator . MarkLabel ( label1 ) ;
CompileConstructorBody ( this , ilGenerator , clinitIndex , invokespecialstubcache ) ;
ilGenerator . MarkLabel ( label2 ) ;
}
// before we call the base class initializer, we need to set the non-final static ConstantValue fields
EmitConstantValueInitialization ( fields , ilGenerator ) ;
EmitCallerIDInitialization ( ilGenerator ) ;
if ( basehasclinit )
{
wrapper . BaseTypeWrapper . EmitRunClassConstructor ( ilGenerator ) ;
}
if ( clinitIndex ! = - 1 )
{
ilGenerator . Emit ( OpCodes . Br , label1 ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ret ) ;
}
2009-04-06 14:10:17 +04:00
ilGenerator . CheckLabels ( ) ;
2008-06-03 10:52:30 +04:00
}
// add all interfaces that we implement (including the magic ones) and handle ghost conversions
2008-08-15 16:01:06 +04:00
ImplementInterfaces ( wrapper . Interfaces , new List < TypeWrapper > ( ) ) ;
2008-06-03 10:52:30 +04:00
// NOTE non-final fields aren't allowed in interfaces so we don't have to initialize constant fields
if ( ! classFile . IsInterface )
{
// if a class has no constructor, we generate one otherwise Ref.Emit will create a default ctor
// and that has several problems:
// - base type may not have an accessible default constructor
// - Ref.Emit uses BaseType.GetConstructors() which may trigger a TypeResolve event
// - we don't want the synthesized constructor to show up in Java
if ( ! hasConstructor )
{
ConstructorBuilder cb = typeBuilder . DefineConstructor ( MethodAttributes . PrivateScope , CallingConventions . Standard , Type . EmptyTypes ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( cb ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldnull ) ;
ilgen . Emit ( OpCodes . Throw ) ;
}
// here we loop thru all the interfaces to explicitly implement any methods that we inherit from
// base types that may have a different name from the name in the interface
// (e.g. interface that has an equals() method that should override System.Object.Equals())
// also deals with interface methods that aren't implemented (generate a stub that throws AbstractMethodError)
// and with methods that aren't public (generate a stub that throws IllegalAccessError)
2008-08-15 16:01:06 +04:00
Dictionary < TypeWrapper , TypeWrapper > doneSet = new Dictionary < TypeWrapper , TypeWrapper > ( ) ;
2008-06-03 10:52:30 +04:00
TypeWrapper [ ] interfaces = wrapper . Interfaces ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
{
interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
}
// if any of our base classes has an incomplete interface implementation we need to look through all
// the base class interfaces to see if we've got an implementation now
TypeWrapper baseTypeWrapper = wrapper . BaseTypeWrapper ;
while ( baseTypeWrapper . HasIncompleteInterfaceImplementation )
{
for ( int i = 0 ; i < baseTypeWrapper . Interfaces . Length ; i + + )
{
baseTypeWrapper . Interfaces [ i ] . ImplementInterfaceMethodStubs ( typeBuilder , wrapper , doneSet ) ;
}
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
}
if ( ! wrapper . IsAbstract & & wrapper . HasUnsupportedAbstractMethods )
{
AddUnsupportedAbstractMethods ( ) ;
}
foreach ( MethodWrapper mw in methods )
{
if ( mw . Name ! = "<init>" & & ! mw . IsStatic & & mw . IsPublic )
{
if ( wrapper . BaseTypeWrapper ! = null & & wrapper . BaseTypeWrapper . HasIncompleteInterfaceImplementation )
{
2008-08-15 16:01:06 +04:00
Dictionary < TypeWrapper , TypeWrapper > hashtable = null ;
2008-06-03 10:52:30 +04:00
TypeWrapper tw = wrapper . BaseTypeWrapper ;
while ( tw . HasIncompleteInterfaceImplementation )
2007-09-07 16:29:21 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( TypeWrapper iface in tw . Interfaces )
2007-09-07 16:29:21 +04:00
{
2008-06-03 10:52:30 +04:00
AddMethodOverride ( mw , ( MethodBuilder ) mw . GetMethod ( ) , iface , mw . Name , mw . Signature , ref hashtable , false ) ;
2007-09-07 16:29:21 +04:00
}
2008-06-03 10:52:30 +04:00
tw = tw . BaseTypeWrapper ;
2007-09-07 16:29:21 +04:00
}
}
2008-06-03 10:52:30 +04:00
if ( true )
2005-06-01 13:49:30 +04:00
{
2008-08-15 16:01:06 +04:00
Dictionary < TypeWrapper , TypeWrapper > hashtable = null ;
2008-06-03 10:52:30 +04:00
foreach ( TypeWrapper iface in wrapper . Interfaces )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
AddMethodOverride ( mw , ( MethodBuilder ) mw . GetMethod ( ) , iface , mw . Name , mw . Signature , ref hashtable , true ) ;
2005-06-01 13:49:30 +04:00
}
2005-11-01 17:01:42 +03:00
}
2005-06-01 13:49:30 +04:00
}
2003-07-31 16:49:29 +04:00
}
2008-06-03 10:52:30 +04:00
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
2008-06-03 10:52:30 +04:00
// If we're an interface that has public/protected fields, we create an inner class
// to expose these fields to C# (which stubbornly refuses to see fields in interfaces).
TypeBuilder tbFields = null ;
if ( classFile . IsInterface & & classFile . IsPublic & & ! wrapper . IsGhost & & classFile . Fields . Length > 0 )
{
// TODO handle name clash
tbFields = typeBuilder . DefineNestedType ( "__Fields" , TypeAttributes . Class | TypeAttributes . NestedPublic | TypeAttributes . Sealed | TypeAttributes . Abstract ) ;
AttributeHelper . HideFromJava ( tbFields ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgenClinit = null ;
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < classFile . Fields . Length ; i + + )
2005-05-24 19:18:27 +04:00
{
2008-06-03 10:52:30 +04:00
ClassFile . Field f = classFile . Fields [ i ] ;
if ( f . ConstantValue ! = null )
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
FieldAttributes attribs = FieldAttributes . Public | FieldAttributes . Static | FieldAttributes . Literal ;
FieldBuilder fb = tbFields . DefineField ( f . Name , fields [ i ] . FieldTypeWrapper . TypeAsSignatureType , attribs ) ;
fb . SetConstant ( f . ConstantValue ) ;
2005-06-01 13:49:30 +04:00
}
2006-05-04 12:09:56 +04:00
else
2005-10-01 15:16:11 +04:00
{
2008-06-03 10:52:30 +04:00
FieldAttributes attribs = FieldAttributes . Public | FieldAttributes . Static | FieldAttributes . InitOnly ;
FieldBuilder fb = tbFields . DefineField ( f . Name , fields [ i ] . FieldTypeWrapper . TypeAsSignatureType , attribs ) ;
if ( ilgenClinit = = null )
{
2008-06-03 16:10:07 +04:00
ilgenClinit = CodeEmitter . Create ( tbFields . DefineTypeInitializer ( ) ) ;
2008-06-03 10:52:30 +04:00
}
wrapper . GetFieldWrapper ( f . Name , f . Signature ) . EmitGet ( ilgenClinit ) ;
ilgenClinit . Emit ( OpCodes . Stsfld , fb ) ;
2005-10-01 15:16:11 +04:00
}
2003-04-26 16:13:02 +04:00
}
2008-06-03 10:52:30 +04:00
if ( ilgenClinit ! = null )
2007-02-01 15:41:22 +03:00
{
2008-06-03 10:52:30 +04:00
ilgenClinit . Emit ( OpCodes . Ret ) ;
}
}
// See if there is any additional metadata
wrapper . EmitMapXmlMetadata ( typeBuilder , classFile , fields , methods ) ;
#endif // STATIC_COMPILER
for ( int i = 0 ; i < classFile . Methods . Length ; i + + )
{
ClassFile . Method m = classFile . Methods [ i ] ;
MethodBase mb = methods [ i ] . GetMethod ( ) ;
2009-03-06 09:43:40 +03:00
if ( mb = = null )
{
continue ;
}
2008-06-03 10:52:30 +04:00
ParameterBuilder returnParameter = null ;
ParameterBuilder [ ] parameterBuilders = null ;
string [ ] parameterNames = null ;
if ( wrapper . GetClassLoader ( ) . EmitDebugInfo
#if STATIC_COMPILER
| | ( classFile . IsPublic & & ( m . IsPublic | | m . IsProtected ) )
#endif
)
{
parameterNames = new string [ methods [ i ] . GetParameters ( ) . Length ] ;
GetParameterNamesFromLVT ( m , parameterNames ) ;
GetParameterNamesFromSig ( m . Signature , parameterNames ) ;
#if STATIC_COMPILER
( ( AotTypeWrapper ) wrapper ) . GetParameterNamesFromXml ( m . Name , m . Signature , parameterNames ) ;
#endif
parameterBuilders = GetParameterBuilders ( mb , parameterNames . Length , parameterNames ) ;
}
#if STATIC_COMPILER
if ( ( m . Modifiers & Modifiers . VarArgs ) ! = 0 & & ! methods [ i ] . HasCallerID )
{
if ( parameterBuilders = = null )
2007-02-01 15:41:22 +03:00
{
2008-06-03 10:52:30 +04:00
parameterBuilders = GetParameterBuilders ( mb , methods [ i ] . GetParameters ( ) . Length , null ) ;
2007-02-01 15:41:22 +03:00
}
2008-06-03 10:52:30 +04:00
if ( parameterBuilders . Length > 0 )
2007-02-01 15:41:22 +03:00
{
2008-06-03 10:52:30 +04:00
AttributeHelper . SetParamArrayAttribute ( parameterBuilders [ parameterBuilders . Length - 1 ] ) ;
2007-02-01 15:41:22 +03:00
}
2006-05-04 12:09:56 +04:00
}
2008-06-03 10:52:30 +04:00
( ( AotTypeWrapper ) wrapper ) . AddXmlMapParameterAttributes ( mb , classFile . Name , m . Name , m . Signature , ref parameterBuilders ) ;
#endif
ConstructorBuilder cb = mb as ConstructorBuilder ;
MethodBuilder mBuilder = mb as MethodBuilder ;
if ( m . Annotations ! = null )
2006-05-04 12:09:56 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( object [ ] def in m . Annotations )
{
Annotation annotation = Annotation . Load ( wrapper . GetClassLoader ( ) , def ) ;
if ( annotation ! = null )
{
if ( cb ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , cb , def ) ;
}
if ( mBuilder ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , mBuilder , def ) ;
annotation . ApplyReturnValue ( wrapper . GetClassLoader ( ) , mBuilder , ref returnParameter , def ) ;
}
}
}
2006-05-04 12:09:56 +04:00
}
2008-06-03 10:52:30 +04:00
if ( m . ParameterAnnotations ! = null )
2006-05-04 12:09:56 +04:00
{
2008-06-03 10:52:30 +04:00
if ( parameterBuilders = = null )
{
parameterBuilders = GetParameterBuilders ( mb , methods [ i ] . GetParameters ( ) . Length , null ) ;
}
object [ ] [ ] defs = m . ParameterAnnotations ;
for ( int j = 0 ; j < defs . Length ; j + + )
{
foreach ( object [ ] def in defs [ j ] )
{
Annotation annotation = Annotation . Load ( wrapper . GetClassLoader ( ) , def ) ;
if ( annotation ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , parameterBuilders [ j ] , def ) ;
}
}
}
2006-05-04 12:09:56 +04:00
}
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
if ( methods [ i ] . HasCallerID )
2006-08-17 17:18:45 +04:00
{
2008-06-03 10:52:30 +04:00
AttributeHelper . SetEditorBrowsableNever ( ( MethodBuilder ) mb ) ;
EmitCallerIDStub ( methods [ i ] , parameterNames ) ;
2006-08-17 17:18:45 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
}
2002-12-18 19:00:25 +03:00
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < classFile . Fields . Length ; i + + )
2005-05-27 16:44:06 +04:00
{
2008-06-03 10:52:30 +04:00
if ( classFile . Fields [ i ] . Annotations ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( object [ ] def in classFile . Fields [ i ] . Annotations )
{
Annotation annotation = Annotation . Load ( wrapper . GetClassLoader ( ) , def ) ;
if ( annotation ! = null )
{
GetterFieldWrapper getter = fields [ i ] as GetterFieldWrapper ;
if ( getter ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , ( MethodBuilder ) getter . GetGetter ( ) , def ) ;
}
else
{
DynamicPropertyFieldWrapper prop = fields [ i ] as DynamicPropertyFieldWrapper ;
if ( prop ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , prop . GetPropertyBuilder ( ) , def ) ;
}
else
{
annotation . Apply ( wrapper . GetClassLoader ( ) , ( FieldBuilder ) fields [ i ] . GetField ( ) , def ) ;
}
}
}
}
2005-06-01 13:49:30 +04:00
}
2005-05-27 16:44:06 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . Annotations ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
foreach ( object [ ] def in classFile . Annotations )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
Annotation annotation = Annotation . Load ( wrapper . GetClassLoader ( ) , def ) ;
if ( annotation ! = null )
{
annotation . Apply ( wrapper . GetClassLoader ( ) , typeBuilder , def ) ;
}
2005-06-01 13:49:30 +04:00
}
}
2003-06-18 12:48:00 +04:00
2008-06-03 10:52:30 +04:00
Type type ;
Profiler . Enter ( "TypeBuilder.CreateType" ) ;
try
2004-08-17 13:05:21 +04:00
{
2008-06-03 10:52:30 +04:00
type = typeBuilder . CreateType ( ) ;
if ( typeCallerID ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
typeCallerID . CreateType ( ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( postFinishProcs ! = null )
{
foreach ( System . Threading . ThreadStart proc in postFinishProcs )
{
proc ( ) ;
}
}
#if STATIC_COMPILER
if ( tbFields ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
tbFields . CreateType ( ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
if ( classFile . IsInterface & & ! classFile . IsPublic )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
( ( DynamicClassLoader ) wrapper . classLoader . GetTypeWrapperFactory ( ) ) . DefineProxyHelper ( type ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2008-06-03 10:52:30 +04:00
finally
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
Profiler . Leave ( "TypeBuilder.CreateType" ) ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
ClassLoaderWrapper . SetWrapperForType ( type , wrapper ) ;
#if STATIC_COMPILER
wrapper . FinishGhostStep2 ( ) ;
#endif
BakedTypeCleanupHack . Process ( wrapper ) ;
return type ;
2002-12-18 19:00:25 +03:00
}
2005-10-01 15:16:11 +04:00
2008-06-03 10:52:30 +04:00
#if ! STATIC_COMPILER
2008-06-03 11:13:49 +04:00
internal static class JniProxyBuilder
2006-04-19 19:49:54 +04:00
{
2008-06-03 10:52:30 +04:00
private static ModuleBuilder mod ;
private static int count ;
2006-12-28 10:46:21 +03:00
2008-06-03 10:52:30 +04:00
static JniProxyBuilder ( )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
AssemblyName name = new AssemblyName ( ) ;
name . Name = "jniproxy" ;
AssemblyBuilder ab = AppDomain . CurrentDomain . DefineDynamicAssembly ( name , JVM . IsSaveDebugImage ? AssemblyBuilderAccess . RunAndSave : AssemblyBuilderAccess . Run ) ;
DynamicClassLoader . RegisterForSaveDebug ( ab ) ;
mod = ab . DefineDynamicModule ( "jniproxy.dll" , "jniproxy.dll" ) ;
CustomAttributeBuilder cab = new CustomAttributeBuilder ( JVM . LoadType ( typeof ( JavaModuleAttribute ) ) . GetConstructor ( Type . EmptyTypes ) , new object [ 0 ] ) ;
mod . SetCustomAttribute ( cab ) ;
2006-12-28 10:46:21 +03:00
}
2008-06-03 16:10:07 +04:00
internal static void Generate ( DynamicTypeWrapper . FinishContext context , CodeEmitter ilGenerator , DynamicTypeWrapper wrapper , MethodWrapper mw , TypeBuilder typeBuilder , ClassFile classFile , ClassFile . Method m , TypeWrapper [ ] args )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
TypeBuilder tb = mod . DefineType ( "__<jni>" + ( count + + ) , TypeAttributes . Public | TypeAttributes . Class ) ;
int instance = m . IsStatic ? 0 : 1 ;
Type [ ] argTypes = new Type [ args . Length + instance + 1 ] ;
if ( instance ! = 0 )
{
argTypes [ 0 ] = typeof ( object ) ;
}
for ( int i = 0 ; i < args . Length ; i + + )
{
// NOTE we take a shortcut here by assuming that all "special" types (i.e. ghost or value types)
// are public and so we can get away with replacing all other types with object.
argTypes [ i + instance ] = ( args [ i ] . IsPrimitive | | args [ i ] . IsGhost | | args [ i ] . IsNonPrimitiveValueType ) ? args [ i ] . TypeAsSignatureType : typeof ( object ) ;
}
argTypes [ argTypes . Length - 1 ] = typeof ( RuntimeMethodHandle ) ;
Type retType = ( mw . ReturnType . IsPrimitive | | mw . ReturnType . IsGhost | | mw . ReturnType . IsNonPrimitiveValueType ) ? mw . ReturnType . TypeAsSignatureType : typeof ( object ) ;
MethodBuilder mb = tb . DefineMethod ( "method" , MethodAttributes . Public | MethodAttributes . Static , retType , argTypes ) ;
AttributeHelper . HideFromJava ( mb ) ;
2008-06-03 16:10:07 +04:00
JniBuilder . Generate ( context , CodeEmitter . Create ( mb ) , wrapper , mw , tb , classFile , m , args , true ) ;
2008-06-03 10:52:30 +04:00
tb . CreateType ( ) ;
for ( int i = 0 ; i < argTypes . Length - 1 ; i + + )
{
ilGenerator . Emit ( OpCodes . Ldarg , ( short ) i ) ;
}
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
ilGenerator . Emit ( OpCodes . Call , mb ) ;
if ( ! mw . ReturnType . IsPrimitive & & ! mw . ReturnType . IsGhost & & ! mw . ReturnType . IsNonPrimitiveValueType )
{
ilGenerator . Emit ( OpCodes . Castclass , mw . ReturnType . TypeAsSignatureType ) ;
}
ilGenerator . Emit ( OpCodes . Ret ) ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 10:52:30 +04:00
#endif // !STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2008-06-03 11:13:49 +04:00
private static class JniBuilder
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
private static readonly Type localRefStructType = StaticCompiler . GetType ( "IKVM.Runtime.JNI+Frame" ) ;
#elif FIRST_PASS
private static readonly Type localRefStructType = null ;
#else
private static readonly Type localRefStructType = JVM . LoadType ( typeof ( IKVM . Runtime . JNI . Frame ) ) ;
#endif
private static readonly MethodInfo jniFuncPtrMethod = localRefStructType . GetMethod ( "GetFuncPtr" ) ;
private static readonly MethodInfo enterLocalRefStruct = localRefStructType . GetMethod ( "Enter" ) ;
private static readonly MethodInfo leaveLocalRefStruct = localRefStructType . GetMethod ( "Leave" ) ;
private static readonly MethodInfo makeLocalRef = localRefStructType . GetMethod ( "MakeLocalRef" ) ;
private static readonly MethodInfo unwrapLocalRef = localRefStructType . GetMethod ( "UnwrapLocalRef" ) ;
private static readonly MethodInfo writeLine = typeof ( Console ) . GetMethod ( "WriteLine" , new Type [ ] { typeof ( object ) } , null ) ;
private static readonly MethodInfo monitorEnter = typeof ( System . Threading . Monitor ) . GetMethod ( "Enter" , new Type [ ] { typeof ( object ) } ) ;
private static readonly MethodInfo monitorExit = typeof ( System . Threading . Monitor ) . GetMethod ( "Exit" , new Type [ ] { typeof ( object ) } ) ;
2005-11-01 17:01:42 +03:00
2008-06-03 16:10:07 +04:00
internal static void Generate ( DynamicTypeWrapper . FinishContext context , CodeEmitter ilGenerator , DynamicTypeWrapper wrapper , MethodWrapper mw , TypeBuilder typeBuilder , ClassFile classFile , ClassFile . Method m , TypeWrapper [ ] args , bool thruProxy )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
LocalBuilder syncObject = null ;
if ( m . IsSynchronized & & m . IsStatic )
2005-11-01 17:01:42 +03:00
{
2009-03-04 08:47:18 +03:00
ilGenerator . Emit ( OpCodes . Ldsfld , context . ClassObjectField ) ;
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Dup ) ;
syncObject = ilGenerator . DeclareLocal ( typeof ( object ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , syncObject ) ;
ilGenerator . Emit ( OpCodes . Call , monitorEnter ) ;
ilGenerator . BeginExceptionBlock ( ) ;
}
string sig = m . Signature . Replace ( '.' , '/' ) ;
// TODO use/unify JNI.METHOD_PTR_FIELD_PREFIX
FieldBuilder methodPtr = typeBuilder . DefineField ( "__<jniptr>" + m . Name + sig , typeof ( IntPtr ) , FieldAttributes . Static | FieldAttributes . PrivateScope ) ;
LocalBuilder localRefStruct = ilGenerator . DeclareLocal ( localRefStructType ) ;
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
ilGenerator . Emit ( OpCodes . Initobj , localRefStructType ) ;
ilGenerator . Emit ( OpCodes . Ldsfld , methodPtr ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel oklabel = ilGenerator . DefineLabel ( ) ;
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Brtrue , oklabel ) ;
if ( thruProxy )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( args . Length + ( mw . IsStatic ? 0 : 1 ) ) ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
ilGenerator . Emit ( OpCodes . Ldstr , classFile . Name . Replace ( '.' , '/' ) ) ;
ilGenerator . Emit ( OpCodes . Ldstr , m . Name ) ;
ilGenerator . Emit ( OpCodes . Ldstr , sig ) ;
ilGenerator . Emit ( OpCodes . Call , jniFuncPtrMethod ) ;
ilGenerator . Emit ( OpCodes . Stsfld , methodPtr ) ;
ilGenerator . MarkLabel ( oklabel ) ;
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
if ( thruProxy )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( args . Length + ( mw . IsStatic ? 0 : 1 ) ) ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldtoken , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , enterLocalRefStruct ) ;
LocalBuilder jnienv = ilGenerator . DeclareLocal ( typeof ( IntPtr ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , jnienv ) ;
ilGenerator . BeginExceptionBlock ( ) ;
TypeWrapper retTypeWrapper = mw . ReturnType ;
if ( ! retTypeWrapper . IsUnloadable & & ! retTypeWrapper . IsPrimitive )
{
// this one is for use after we return from "calli"
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
}
ilGenerator . Emit ( OpCodes . Ldloc , jnienv ) ;
Type [ ] modargs = new Type [ args . Length + 2 ] ;
modargs [ 0 ] = typeof ( IntPtr ) ;
modargs [ 1 ] = typeof ( IntPtr ) ;
for ( int i = 0 ; i < args . Length ; i + + )
{
modargs [ i + 2 ] = args [ i ] . TypeAsSignatureType ;
}
int add = 0 ;
if ( ! m . IsStatic )
{
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
ilGenerator . Emit ( OpCodes . Ldarg_0 ) ;
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
add = 1 ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
2009-03-04 08:47:18 +03:00
ilGenerator . Emit ( OpCodes . Ldsfld , context . ClassObjectField ) ;
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
}
for ( int j = 0 ; j < args . Length ; j + + )
{
if ( args [ j ] . IsUnloadable | | ! args [ j ] . IsPrimitive )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
if ( ! args [ j ] . IsUnloadable & & args [ j ] . IsNonPrimitiveValueType )
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
args [ j ] . EmitBox ( ilGenerator ) ;
}
else if ( ! args [ j ] . IsUnloadable & & args [ j ] . IsGhost )
{
ilGenerator . Emit ( OpCodes . Ldarga_S , ( byte ) ( j + add ) ) ;
ilGenerator . Emit ( OpCodes . Ldfld , args [ j ] . GhostRefField ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
}
ilGenerator . Emit ( OpCodes . Call , makeLocalRef ) ;
modargs [ j + 2 ] = typeof ( IntPtr ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
else
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ldarg_S , ( byte ) ( j + add ) ) ;
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ldsfld , methodPtr ) ;
Type realRetType ;
if ( retTypeWrapper = = PrimitiveTypeWrapper . BOOLEAN )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
realRetType = typeof ( byte ) ;
}
else if ( retTypeWrapper . IsPrimitive )
{
realRetType = retTypeWrapper . TypeAsSignatureType ;
}
else
{
realRetType = typeof ( IntPtr ) ;
}
ilGenerator . EmitCalli ( OpCodes . Calli , System . Runtime . InteropServices . CallingConvention . StdCall , realRetType , modargs ) ;
LocalBuilder retValue = null ;
if ( retTypeWrapper ! = PrimitiveTypeWrapper . VOID )
{
if ( ! retTypeWrapper . IsUnloadable & & ! retTypeWrapper . IsPrimitive )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Call , unwrapLocalRef ) ;
if ( retTypeWrapper . IsNonPrimitiveValueType )
{
retTypeWrapper . EmitUnbox ( ilGenerator ) ;
}
else if ( retTypeWrapper . IsGhost )
{
LocalBuilder ghost = ilGenerator . DeclareLocal ( retTypeWrapper . TypeAsSignatureType ) ;
LocalBuilder obj = ilGenerator . DeclareLocal ( typeof ( object ) ) ;
ilGenerator . Emit ( OpCodes . Stloc , obj ) ;
ilGenerator . Emit ( OpCodes . Ldloca , ghost ) ;
ilGenerator . Emit ( OpCodes . Ldloc , obj ) ;
ilGenerator . Emit ( OpCodes . Stfld , retTypeWrapper . GhostRefField ) ;
ilGenerator . Emit ( OpCodes . Ldloc , ghost ) ;
}
else
{
ilGenerator . Emit ( OpCodes . Castclass , retTypeWrapper . TypeAsTBD ) ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
retValue = ilGenerator . DeclareLocal ( retTypeWrapper . TypeAsSignatureType ) ;
ilGenerator . Emit ( OpCodes . Stloc , retValue ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
ilGenerator . BeginCatchBlock ( typeof ( object ) ) ;
ilGenerator . EmitWriteLine ( "*** exception in native code ***" ) ;
ilGenerator . Emit ( OpCodes . Call , writeLine ) ;
ilGenerator . Emit ( OpCodes . Rethrow ) ;
ilGenerator . BeginFinallyBlock ( ) ;
ilGenerator . Emit ( OpCodes . Ldloca , localRefStruct ) ;
ilGenerator . Emit ( OpCodes . Call , leaveLocalRefStruct ) ;
ilGenerator . EndExceptionBlock ( ) ;
if ( m . IsSynchronized & & m . IsStatic )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . BeginFinallyBlock ( ) ;
ilGenerator . Emit ( OpCodes . Ldloc , syncObject ) ;
ilGenerator . Emit ( OpCodes . Call , monitorExit ) ;
ilGenerator . EndExceptionBlock ( ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
if ( retTypeWrapper ! = PrimitiveTypeWrapper . VOID )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ldloc , retValue ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
ilGenerator . Emit ( OpCodes . Ret ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
}
2008-06-03 11:13:49 +04:00
private static class TraceHelper
2008-06-03 10:52:30 +04:00
{
#if STATIC_COMPILER
private readonly static MethodInfo methodIsTracedMethod = typeof ( Tracer ) . GetMethod ( "IsTracedMethod" ) ;
#endif
private readonly static MethodInfo methodMethodInfo = typeof ( Tracer ) . GetMethod ( "MethodInfo" ) ;
2008-06-03 16:10:07 +04:00
internal static void EmitMethodTrace ( CodeEmitter ilgen , string tracemessage )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( Tracer . IsTracedMethod ( tracemessage ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 16:10:07 +04:00
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
// TODO this should be a boolean field test instead of a call to Tracer.IsTracedMessage
ilgen . Emit ( OpCodes . Ldstr , tracemessage ) ;
ilgen . Emit ( OpCodes . Call , methodIsTracedMethod ) ;
ilgen . Emit ( OpCodes . Brfalse_S , label ) ;
#endif
ilgen . Emit ( OpCodes . Ldstr , tracemessage ) ;
ilgen . Emit ( OpCodes . Call , methodMethodInfo ) ;
ilgen . MarkLabel ( label ) ;
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
}
#if STATIC_COMPILER
private void EmitCallerIDStub ( MethodWrapper mw , string [ ] parameterNames )
{
Type [ ] p = mw . GetParametersForDefineMethod ( ) ;
Type [ ] parameterTypes = new Type [ p . Length - 1 ] ;
for ( int i = 0 ; i < parameterTypes . Length ; i + + )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
parameterTypes [ i ] = p [ i ] ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
MethodAttributes attribs = MethodAttributes . HideBySig ;
int argcount = parameterTypes . Length ;
if ( mw . IsStatic )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
attribs | = MethodAttributes . Static ;
}
else
{
argcount + + ;
}
if ( mw . IsPublic )
{
attribs | = MethodAttributes . Public ;
}
else if ( mw . IsProtected )
{
attribs | = MethodAttributes . FamORAssem ;
}
else if ( mw . IsPrivate )
{
attribs | = MethodAttributes . Private ;
}
else
{
attribs | = MethodAttributes . Assembly ;
}
MethodBuilder mb = typeBuilder . DefineMethod ( mw . Name , attribs , mw . ReturnTypeForDefineMethod , parameterTypes ) ;
AttributeHelper . HideFromJava ( mb ) ;
mb . SetImplementationFlags ( MethodImplAttributes . NoInlining ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < argcount ; i + + )
{
if ( parameterNames ! = null & & ( mw . IsStatic | | i > 0 ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ParameterBuilder pb = mb . DefineParameter ( mw . IsStatic ? i + 1 : i , ParameterAttributes . None , parameterNames [ mw . IsStatic ? i : i - 1 ] ) ;
if ( i = = argcount - 1 & & ( mw . Modifiers & Modifiers . VarArgs ) ! = 0 )
{
AttributeHelper . SetParamArrayAttribute ( pb ) ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg , ( short ) i ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldc_I4_1 ) ;
ilgen . Emit ( OpCodes . Ldc_I4_0 ) ;
ilgen . Emit ( OpCodes . Newobj , typeof ( StackFrame ) . GetConstructor ( new Type [ ] { typeof ( int ) , typeof ( bool ) } ) ) ;
MethodWrapper callerID = CoreClasses . ikvm . @internal . CallerID . Wrapper . GetMethodWrapper ( "create" , "(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;" , false ) ;
callerID . Link ( ) ;
callerID . EmitCall ( ilgen ) ;
if ( mw . IsStatic )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
mw . EmitCall ( ilgen ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
else
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
mw . EmitCallvirt ( ilgen ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ret ) ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
#endif // STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2008-08-15 16:01:06 +04:00
private void AddMethodOverride ( MethodWrapper method , MethodBuilder mb , TypeWrapper iface , string name , string sig , ref Dictionary < TypeWrapper , TypeWrapper > hashtable , bool unloadableOnly )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( hashtable ! = null & & hashtable . ContainsKey ( iface ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
return ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
MethodWrapper mw = iface . GetMethodWrapper ( name , sig , false ) ;
if ( mw ! = null )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( hashtable = = null )
{
2008-08-15 16:01:06 +04:00
hashtable = new Dictionary < TypeWrapper , TypeWrapper > ( ) ;
2008-06-03 10:52:30 +04:00
}
hashtable . Add ( iface , iface ) ;
if ( CheckRequireOverrideStub ( method , mw ) )
{
JavaTypeImpl . GenerateUnloadableOverrideStub ( wrapper , typeBuilder , mw , mb , method . ReturnTypeForDefineMethod , method . GetParametersForDefineMethod ( ) ) ;
}
else if ( ! unloadableOnly )
{
typeBuilder . DefineMethodOverride ( mb , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
foreach ( TypeWrapper iface2 in iface . Interfaces )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
AddMethodOverride ( method , mb , iface2 , name , sig , ref hashtable , unloadableOnly ) ;
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
private static bool CheckRequireOverrideStub ( MethodWrapper mw1 , MethodWrapper mw2 )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
// TODO this is too late to generate LinkageErrors so we need to figure this out earlier
if ( mw1 . ReturnType ! = mw2 . ReturnType & & ! ( mw1 . ReturnType . IsUnloadable & & mw2 . ReturnType . IsUnloadable ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
return true ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
TypeWrapper [ ] args1 = mw1 . GetParameters ( ) ;
TypeWrapper [ ] args2 = mw2 . GetParameters ( ) ;
for ( int i = 0 ; i < args1 . Length ; i + + )
{
if ( args1 [ i ] ! = args2 [ i ] & & ! ( args1 [ i ] . IsUnloadable & & args2 [ i ] . IsUnloadable ) )
{
return true ;
}
}
return false ;
2005-11-01 17:01:42 +03:00
}
2008-08-15 16:01:06 +04:00
private void ImplementInterfaces ( TypeWrapper [ ] interfaces , List < TypeWrapper > interfaceList )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
foreach ( TypeWrapper iface in interfaces )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( ! interfaceList . Contains ( iface ) )
{
interfaceList . Add ( iface ) ;
// NOTE we're using TypeAsBaseType for the interfaces!
Type ifaceType = iface . TypeAsBaseType ;
2008-11-14 11:42:07 +03:00
if ( ! iface . IsPublic & & ! ReflectUtil . IsSameAssembly ( ifaceType , typeBuilder ) )
2008-06-03 10:52:30 +04:00
{
ifaceType = ifaceType . Assembly . GetType ( DynamicClassLoader . GetProxyHelperName ( ifaceType ) ) ;
}
typeBuilder . AddInterfaceImplementation ( ifaceType ) ;
#if STATIC_COMPILER
if ( ! wrapper . IsInterface )
{
// look for "magic" interfaces that imply a .NET interface
if ( iface . GetClassLoader ( ) = = CoreClasses . java . lang . Object . Wrapper . GetClassLoader ( ) )
{
if ( iface . Name = = "java.lang.Iterable"
2008-08-15 16:01:06 +04:00
& & ! wrapper . ImplementsInterface ( ClassLoaderWrapper . GetWrapperFromType ( typeof ( System . Collections . IEnumerable ) ) ) )
2008-06-03 10:52:30 +04:00
{
TypeWrapper enumeratorType = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedNameFast ( "ikvm.lang.IterableEnumerator" ) ;
if ( enumeratorType ! = null )
{
2008-08-15 16:01:06 +04:00
typeBuilder . AddInterfaceImplementation ( typeof ( System . Collections . IEnumerable ) ) ;
2008-06-03 10:52:30 +04:00
// FXBUG we're using the same method name as the C# compiler here because both the .NET and Mono implementations of Xml serialization depend on this method name
2008-08-15 16:01:06 +04:00
MethodBuilder mb = typeBuilder . DefineMethod ( "System.Collections.IEnumerable.GetEnumerator" , MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . NewSlot | MethodAttributes . Final | MethodAttributes . SpecialName , typeof ( System . Collections . IEnumerator ) , Type . EmptyTypes ) ;
2008-06-03 10:52:30 +04:00
AttributeHelper . HideFromJava ( mb ) ;
2008-08-15 16:01:06 +04:00
typeBuilder . DefineMethodOverride ( mb , typeof ( System . Collections . IEnumerable ) . GetMethod ( "GetEnumerator" ) ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
MethodWrapper mw = enumeratorType . GetMethodWrapper ( "<init>" , "(Ljava.lang.Iterable;)V" , false ) ;
mw . Link ( ) ;
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
}
else if ( iface . Name = = "java.io.Closeable"
& & ! wrapper . ImplementsInterface ( ClassLoaderWrapper . GetWrapperFromType ( typeof ( IDisposable ) ) ) )
{
typeBuilder . AddInterfaceImplementation ( typeof ( IDisposable ) ) ;
MethodBuilder mb = typeBuilder . DefineMethod ( "__<>Dispose" , MethodAttributes . Private | MethodAttributes . Virtual | MethodAttributes . NewSlot | MethodAttributes . Final | MethodAttributes . SpecialName , typeof ( void ) , Type . EmptyTypes ) ;
typeBuilder . DefineMethodOverride ( mb , typeof ( IDisposable ) . GetMethod ( "Dispose" ) ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
MethodWrapper mw = iface . GetMethodWrapper ( "close" , "()V" , false ) ;
mw . Link ( ) ;
mw . EmitCallvirt ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
}
// if we implement a ghost interface, add an implicit conversion to the ghost reference value type
if ( iface . IsGhost & & wrapper . IsPublic )
{
MethodBuilder mb = typeBuilder . DefineMethod ( "op_Implicit" , MethodAttributes . HideBySig | MethodAttributes . Public | MethodAttributes . Static | MethodAttributes . SpecialName , iface . TypeAsSignatureType , new Type [ ] { wrapper . TypeAsSignatureType } ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ilgen = CodeEmitter . Create ( mb ) ;
2008-06-03 10:52:30 +04:00
LocalBuilder local = ilgen . DeclareLocal ( iface . TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Stfld , iface . GhostRefField ) ;
ilgen . Emit ( OpCodes . Ldloca , local ) ;
ilgen . Emit ( OpCodes . Ldobj , iface . TypeAsSignatureType ) ;
ilgen . Emit ( OpCodes . Ret ) ;
}
}
#endif // STATIC_COMPILER
// NOTE we're recursively "implementing" all interfaces that we inherit from the interfaces we implement.
// The C# compiler also does this and the Compact Framework requires it.
ImplementInterfaces ( iface . Interfaces , interfaceList ) ;
}
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
private void AddUnsupportedAbstractMethods ( )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
foreach ( MethodBase mb in wrapper . BaseTypeWrapper . TypeAsBaseType . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
if ( DotNetTypeWrapper . IsUnsupportedAbstractMethod ( mb ) )
{
GenerateUnsupportedAbstractMethodStub ( mb ) ;
}
2005-11-01 17:01:42 +03:00
}
2008-08-15 16:01:06 +04:00
Dictionary < MethodBase , MethodBase > h = new Dictionary < MethodBase , MethodBase > ( ) ;
2008-06-03 10:52:30 +04:00
TypeWrapper tw = wrapper ;
while ( tw ! = null )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
foreach ( TypeWrapper iface in tw . Interfaces )
{
foreach ( MethodBase mb in iface . TypeAsBaseType . GetMethods ( BindingFlags . Public | BindingFlags . Instance ) )
{
if ( ! h . ContainsKey ( mb ) )
{
h . Add ( mb , mb ) ;
if ( DotNetTypeWrapper . IsUnsupportedAbstractMethod ( mb ) )
{
GenerateUnsupportedAbstractMethodStub ( mb ) ;
}
}
}
}
tw = tw . BaseTypeWrapper ;
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 10:52:30 +04:00
private void GenerateUnsupportedAbstractMethodStub ( MethodBase mb )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
Type [ ] parameterTypes = new Type [ parameters . Length ] ;
for ( int i = 0 ; i < parameters . Length ; i + + )
2005-11-01 17:01:42 +03:00
{
2008-06-03 10:52:30 +04:00
parameterTypes [ i ] = parameters [ i ] . ParameterType ;
2005-11-01 17:01:42 +03:00
}
2008-06-03 10:52:30 +04:00
MethodAttributes attr = MethodAttributes . NewSlot | MethodAttributes . Virtual | MethodAttributes . Private ;
MethodBuilder m = typeBuilder . DefineMethod ( "__<unsupported>" + mb . DeclaringType . FullName + "/" + mb . Name , attr , ( ( MethodInfo ) mb ) . ReturnType , parameterTypes ) ;
2008-06-03 16:10:07 +04:00
EmitHelper . Throw ( CodeEmitter . Create ( m ) , "java.lang.AbstractMethodError" , "Method " + mb . DeclaringType . FullName + "." + mb . Name + " is unsupported by IKVM." ) ;
2008-06-03 10:52:30 +04:00
typeBuilder . DefineMethodOverride ( m , ( MethodInfo ) mb ) ;
2005-11-01 17:01:42 +03:00
}
2005-06-01 13:49:30 +04:00
2008-08-15 16:01:06 +04:00
private void CompileConstructorBody ( FinishContext context , CodeEmitter ilGenerator , int methodIndex , Dictionary < MethodKey , MethodInfo > invokespecialstubcache )
2003-02-18 12:30:34 +03:00
{
2008-06-03 10:52:30 +04:00
MethodWrapper [ ] methods = wrapper . GetMethods ( ) ;
ClassFile . Method m = classFile . Methods [ methodIndex ] ;
TraceHelper . EmitMethodTrace ( ilGenerator , classFile . Name + "." + m . Name + m . Signature ) ;
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
2008-06-03 10:52:30 +04:00
// do we have a native implementation in map.xml?
if ( wrapper . EmitMapXmlMethodBody ( ilGenerator , classFile , m ) )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
return ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
#endif
LineNumberTableAttribute . LineNumberWriter lineNumberTable = null ;
bool nonLeaf = false ;
Compiler . Compile ( context , wrapper , methods [ methodIndex ] , classFile , m , ilGenerator , ref nonLeaf , invokespecialstubcache , ref lineNumberTable ) ;
if ( lineNumberTable ! = null )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
#if STATIC_COMPILER
AttributeHelper . SetLineNumberTable ( methods [ methodIndex ] . GetMethod ( ) , lineNumberTable ) ;
#else // STATIC_COMPILER
if ( wrapper . lineNumberTables = = null )
{
wrapper . lineNumberTables = new byte [ methods . Length ] [ ] ;
}
wrapper . lineNumberTables [ methodIndex ] = lineNumberTable . ToArray ( ) ;
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
}
2008-06-03 10:52:30 +04:00
private static bool IsCompatibleArgList ( TypeWrapper [ ] caller , TypeWrapper [ ] callee )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
if ( caller . Length = = callee . Length )
2005-06-01 13:49:30 +04:00
{
2008-06-03 10:52:30 +04:00
for ( int i = 0 ; i < caller . Length ; i + + )
{
if ( ! caller [ i ] . IsAssignableTo ( callee [ i ] ) )
{
return false ;
}
}
return true ;
2005-06-01 13:49:30 +04:00
}
2008-06-03 10:52:30 +04:00
return false ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
2008-06-03 16:10:07 +04:00
private void EmitCallerIDInitialization ( CodeEmitter ilGenerator )
2005-08-24 12:14:23 +04:00
{
2008-06-03 10:52:30 +04:00
if ( callerIDField ! = null )
2005-08-24 12:14:23 +04:00
{
2008-06-03 10:52:30 +04:00
TypeWrapper tw = CoreClasses . ikvm . @internal . CallerID . Wrapper ;
// we need to prohibit this optimization at runtime, because proxy classes may be injected into the boot class loader,
// but they don't actually have access to core library internals
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
2008-06-03 10:52:30 +04:00
if ( tw . GetClassLoader ( ) = = wrapper . GetClassLoader ( ) )
{
MethodWrapper create = tw . GetMethodWrapper ( "create" , "(Lcli.System.RuntimeTypeHandle;)Likvm.internal.CallerID;" , false ) ;
ilGenerator . Emit ( OpCodes . Ldtoken , this . typeBuilder ) ;
create . Link ( ) ;
create . EmitCall ( ilGenerator ) ;
}
else
#endif
{
typeCallerID = typeBuilder . DefineNestedType ( "__<CallerID>" , TypeAttributes . Sealed | TypeAttributes . NestedPrivate , tw . TypeAsBaseType ) ;
ConstructorBuilder cb = typeCallerID . DefineConstructor ( MethodAttributes . Assembly , CallingConventions . Standard , null ) ;
2008-06-03 16:10:07 +04:00
CodeEmitter ctorIlgen = CodeEmitter . Create ( cb ) ;
2008-06-03 10:52:30 +04:00
ctorIlgen . Emit ( OpCodes . Ldarg_0 ) ;
MethodWrapper mw = tw . GetMethodWrapper ( "<init>" , "()V" , false ) ;
mw . Link ( ) ;
mw . EmitCall ( ctorIlgen ) ;
ctorIlgen . Emit ( OpCodes . Ret ) ;
ilGenerator . Emit ( OpCodes . Newobj , cb ) ;
}
ilGenerator . Emit ( OpCodes . Stsfld , callerIDField ) ;
2006-12-28 10:46:21 +03:00
}
}
2008-06-03 16:10:07 +04:00
private void EmitConstantValueInitialization ( FieldWrapper [ ] fields , CodeEmitter ilGenerator )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
ClassFile . Field [ ] flds = classFile . Fields ;
for ( int i = 0 ; i < flds . Length ; i + + )
2006-12-28 10:46:21 +03:00
{
2008-06-03 10:52:30 +04:00
ClassFile . Field f = flds [ i ] ;
if ( f . IsStatic & & ! f . IsFinal )
{
object constant = f . ConstantValue ;
if ( constant ! = null )
{
if ( constant is int )
{
ilGenerator . Emit ( OpCodes . Ldc_I4 , ( int ) constant ) ;
}
else if ( constant is long )
{
ilGenerator . Emit ( OpCodes . Ldc_I8 , ( long ) constant ) ;
}
else if ( constant is double )
{
ilGenerator . Emit ( OpCodes . Ldc_R8 , ( double ) constant ) ;
}
else if ( constant is float )
{
ilGenerator . Emit ( OpCodes . Ldc_R4 , ( float ) constant ) ;
}
else if ( constant is string )
{
ilGenerator . Emit ( OpCodes . Ldstr , ( string ) constant ) ;
}
else
{
throw new InvalidOperationException ( ) ;
}
fields [ i ] . EmitSet ( ilGenerator ) ;
}
}
2006-12-28 10:46:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
}
2007-04-15 12:01:19 +04:00
protected static void GetParameterNamesFromLVT ( ClassFile . Method m , string [ ] parameterNames )
2005-06-01 13:49:30 +04:00
{
ClassFile . Method . LocalVariableTableEntry [ ] localVars = m . LocalVariableTableAttribute ;
if ( localVars ! = null )
2005-05-30 19:30:13 +04:00
{
2007-03-05 15:37:03 +03:00
for ( int i = m . IsStatic ? 0 : 1 , pos = 0 ; i < m . ArgMap . Length ; i + + )
2005-05-30 19:30:13 +04:00
{
2007-03-05 15:37:03 +03:00
// skip double & long fillers
2005-06-01 13:49:30 +04:00
if ( m . ArgMap [ i ] ! = - 1 )
2005-05-30 19:30:13 +04:00
{
2007-03-05 15:37:03 +03:00
if ( parameterNames [ pos ] = = null )
2005-05-30 19:30:13 +04:00
{
2007-03-05 15:37:03 +03:00
for ( int j = 0 ; j < localVars . Length ; j + + )
2005-05-30 19:30:13 +04:00
{
2007-03-05 15:37:03 +03:00
if ( localVars [ j ] . index = = i )
2005-06-01 13:49:30 +04:00
{
2007-03-05 15:37:03 +03:00
parameterNames [ pos ] = localVars [ j ] . name ;
break ;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
}
2007-03-05 15:37:03 +03:00
pos + + ;
2005-05-30 19:30:13 +04:00
}
}
}
2004-01-18 01:46:43 +03:00
}
2007-04-15 12:01:19 +04:00
protected static void GetParameterNamesFromSig ( string sig , string [ ] parameterNames )
2004-03-08 18:18:47 +03:00
{
2008-08-15 16:01:06 +04:00
List < string > names = new List < string > ( ) ;
2005-06-01 13:49:30 +04:00
for ( int i = 1 ; sig [ i ] ! = ')' ; i + + )
2005-05-30 19:30:13 +04:00
{
if ( sig [ i ] = = 'L' )
{
i + + ;
int end = sig . IndexOf ( ';' , i ) ;
2005-06-01 13:49:30 +04:00
names . Add ( GetParameterName ( sig . Substring ( i , end - i ) ) ) ;
2005-05-30 19:30:13 +04:00
i = end ;
}
2005-06-01 13:49:30 +04:00
else if ( sig [ i ] = = '[' )
{
while ( sig [ + + i ] = = '[' ) ;
if ( sig [ i ] = = 'L' )
{
i + + ;
int end = sig . IndexOf ( ';' , i ) ;
names . Add ( GetParameterName ( sig . Substring ( i , end - i ) ) + "arr" ) ;
i = end ;
}
else
{
switch ( sig [ i ] )
{
case 'B' :
case 'Z' :
names . Add ( "barr" ) ;
break ;
case 'C' :
names . Add ( "charr" ) ;
break ;
case 'S' :
names . Add ( "sarr" ) ;
break ;
case 'I' :
names . Add ( "iarr" ) ;
break ;
case 'J' :
names . Add ( "larr" ) ;
break ;
case 'F' :
names . Add ( "farr" ) ;
break ;
case 'D' :
names . Add ( "darr" ) ;
break ;
}
}
}
2005-05-30 19:30:13 +04:00
else
{
switch ( sig [ i ] )
{
case 'B' :
case 'Z' :
2005-06-01 13:49:30 +04:00
names . Add ( "b" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'C' :
2005-06-01 13:49:30 +04:00
names . Add ( "ch" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'S' :
2005-06-01 13:49:30 +04:00
names . Add ( "s" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'I' :
2005-06-01 13:49:30 +04:00
names . Add ( "i" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'J' :
2005-06-01 13:49:30 +04:00
names . Add ( "l" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'F' :
2005-06-01 13:49:30 +04:00
names . Add ( "f" ) ;
2005-05-30 19:30:13 +04:00
break ;
case 'D' :
2005-06-01 13:49:30 +04:00
names . Add ( "d" ) ;
2005-05-30 19:30:13 +04:00
break ;
}
}
}
2007-04-15 12:01:19 +04:00
for ( int i = 0 ; i < parameterNames . Length ; i + + )
2005-05-30 19:30:13 +04:00
{
2007-04-15 12:01:19 +04:00
if ( parameterNames [ i ] = = null )
2005-05-30 19:30:13 +04:00
{
2007-04-15 12:01:19 +04:00
parameterNames [ i ] = ( string ) names [ i ] ;
2005-06-01 13:49:30 +04:00
}
2007-04-15 12:01:19 +04:00
}
}
protected static ParameterBuilder [ ] GetParameterBuilders ( MethodBase mb , int parameterCount , string [ ] parameterNames )
{
ParameterBuilder [ ] parameterBuilders = new ParameterBuilder [ parameterCount ] ;
2008-08-15 16:01:06 +04:00
Dictionary < string , int > clashes = null ;
2007-04-15 12:01:19 +04:00
for ( int i = 0 ; i < parameterBuilders . Length ; i + + )
{
string name = null ;
if ( parameterNames ! = null )
2005-06-01 13:49:30 +04:00
{
2007-04-15 12:01:19 +04:00
name = parameterNames [ i ] ;
if ( Array . IndexOf ( parameterNames , name , i + 1 ) > = 0 | | ( clashes ! = null & & clashes . ContainsKey ( name ) ) )
2005-06-01 13:49:30 +04:00
{
2007-04-15 12:01:19 +04:00
if ( clashes = = null )
{
2008-08-15 16:01:06 +04:00
clashes = new Dictionary < string , int > ( ) ;
2007-04-15 12:01:19 +04:00
}
int clash = 1 ;
if ( clashes . ContainsKey ( name ) )
{
2008-08-15 16:01:06 +04:00
clash = clashes [ name ] + 1 ;
2007-04-15 12:01:19 +04:00
}
clashes [ name ] = clash ;
name + = clash ;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
2007-04-15 12:01:19 +04:00
MethodBuilder mBuilder = mb as MethodBuilder ;
if ( mBuilder ! = null )
2005-06-01 13:49:30 +04:00
{
2007-04-15 12:01:19 +04:00
parameterBuilders [ i ] = mBuilder . DefineParameter ( i + 1 , ParameterAttributes . None , name ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2007-04-15 12:01:19 +04:00
parameterBuilders [ i ] = ( ( ConstructorBuilder ) mb ) . DefineParameter ( i + 1 , ParameterAttributes . None , name ) ;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
return parameterBuilders ;
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
private static string GetParameterName ( string type )
2004-01-18 01:46:43 +03:00
{
2005-06-01 13:49:30 +04:00
if ( type = = "java.lang.String" )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "str" ;
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type = = "java.lang.Object" )
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "obj" ;
2005-05-30 19:30:13 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
for ( int i = type . LastIndexOf ( '.' ) + 1 ; i < type . Length ; i + + )
{
if ( char . IsUpper ( type , i ) )
{
sb . Append ( char . ToLower ( type [ i ] ) ) ;
}
}
return sb . ToString ( ) ;
2005-05-30 19:30:13 +04:00
}
}
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
2007-06-28 14:32:50 +04:00
protected abstract void AddMapXmlFields ( ref FieldWrapper [ ] fields ) ;
2008-06-03 16:10:07 +04:00
protected abstract bool EmitMapXmlMethodBody ( CodeEmitter ilgen , ClassFile f , ClassFile . Method m ) ;
2006-09-12 13:57:36 +04:00
protected abstract void EmitMapXmlMetadata ( TypeBuilder typeBuilder , ClassFile classFile , FieldWrapper [ ] fields , MethodWrapper [ ] methods ) ;
protected abstract MethodBuilder DefineGhostMethod ( string name , MethodAttributes attribs , MethodWrapper mw ) ;
protected abstract void FinishGhost ( TypeBuilder typeBuilder , MethodWrapper [ ] methods ) ;
protected abstract void FinishGhostStep2 ( ) ;
protected abstract TypeBuilder DefineGhostType ( string mangledTypeName , TypeAttributes typeAttribs ) ;
#endif // STATIC_COMPILER
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual bool IsPInvokeMethod ( ClassFile . Method m )
{
2006-06-15 16:29:11 +04:00
if ( m . Annotations ! = null )
{
foreach ( object [ ] annot in m . Annotations )
{
if ( "Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;" . Equals ( annot [ 1 ] ) )
{
return true ;
}
}
}
2005-06-01 13:49:30 +04:00
return false ;
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
internal override MethodBase LinkMethod ( MethodWrapper mw )
{
mw . AssertLinked ( ) ;
return impl . LinkMethod ( mw ) ;
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField ( FieldWrapper fw )
{
fw . AssertLinked ( ) ;
return impl . LinkField ( fw ) ;
}
2005-08-24 12:14:23 +04:00
2008-06-03 16:10:07 +04:00
internal override void EmitRunClassConstructor ( CodeEmitter ilgen )
2005-08-24 12:14:23 +04:00
{
impl . EmitRunClassConstructor ( ilgen ) ;
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return impl . GetGenericSignature ( ) ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
return impl . GetGenericMethodSignature ( i ) ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
FieldWrapper [ ] fields = GetFields ( ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
{
if ( fields [ i ] = = fw )
{
return impl . GetGenericFieldSignature ( i + GetMethods ( ) . Length ) ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return impl . GetEnclosingMethod ( ) ;
}
2005-11-01 17:01:42 +03:00
2006-05-04 12:09:56 +04:00
internal override string GetSourceFileName ( )
{
return sourceFileName ;
}
2008-05-20 11:43:42 +04:00
#if ! STATIC_COMPILER
2006-05-05 12:16:18 +04:00
private int GetMethodBaseToken ( MethodBase mb )
{
ConstructorInfo ci = mb as ConstructorInfo ;
if ( ci ! = null )
{
2006-07-26 18:16:52 +04:00
return classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . GetConstructorToken ( ci ) . Token ;
2006-05-05 12:16:18 +04:00
}
else
{
2006-07-26 18:16:52 +04:00
return classLoader . GetTypeWrapperFactory ( ) . ModuleBuilder . GetMethodToken ( ( MethodInfo ) mb ) . Token ;
2006-05-05 12:16:18 +04:00
}
}
2007-12-28 13:22:06 +03:00
2006-05-04 12:09:56 +04:00
internal override int GetSourceLineNumber ( MethodBase mb , int ilOffset )
{
if ( lineNumberTables ! = null )
{
2006-05-05 12:16:18 +04:00
int token = GetMethodBaseToken ( mb ) ;
2006-05-04 12:09:56 +04:00
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
2006-05-05 12:16:18 +04:00
if ( GetMethodBaseToken ( methods [ i ] . GetMethod ( ) ) = = token )
2006-05-04 12:09:56 +04:00
{
if ( lineNumberTables [ i ] ! = null )
{
return new LineNumberTableAttribute ( lineNumberTables [ i ] ) . GetLineNumber ( ilOffset ) ;
}
break ;
}
}
}
return - 1 ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
object [ ] annotations = impl . GetDeclaredAnnotations ( ) ;
2006-04-19 19:49:54 +04:00
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int i = 0 ; i < annotations . Length ; i + + )
{
2007-12-19 14:28:09 +03:00
objs [ i ] = JVM . NewAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ i ] ) ;
2006-04-19 19:49:54 +04:00
}
return objs ;
}
return null ;
}
internal override object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
object [ ] annotations = impl . GetMethodAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
2007-12-19 14:28:09 +03:00
objs [ j ] = JVM . NewAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] ) ;
2006-04-19 19:49:54 +04:00
}
return objs ;
}
return null ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
object [ ] [ ] annotations = impl . GetParameterAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] [ ] objs = new object [ annotations . Length ] [ ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
objs [ j ] = new object [ annotations [ j ] . Length ] ;
for ( int k = 0 ; k < annotations [ j ] . Length ; k + + )
{
2007-12-19 14:28:09 +03:00
objs [ j ] [ k ] = JVM . NewAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] [ k ] ) ;
2006-04-19 19:49:54 +04:00
}
}
return objs ;
}
return null ;
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
internal override object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
FieldWrapper [ ] fields = GetFields ( ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
2005-11-01 17:01:42 +03:00
{
2006-04-19 19:49:54 +04:00
if ( fields [ i ] = = fw )
{
object [ ] annotations = impl . GetFieldAnnotations ( i ) ;
if ( annotations ! = null )
{
object [ ] objs = new object [ annotations . Length ] ;
for ( int j = 0 ; j < annotations . Length ; j + + )
{
2007-12-19 14:28:09 +03:00
objs [ j ] = JVM . NewAnnotation ( GetClassLoader ( ) . GetJavaClassLoader ( ) , annotations [ j ] ) ;
2006-04-19 19:49:54 +04:00
}
return objs ;
}
return null ;
}
2005-11-01 17:01:42 +03:00
}
2006-04-19 19:49:54 +04:00
Debug . Fail ( "Unreachable code" ) ;
return null ;
2005-11-01 17:01:42 +03:00
}
internal override object GetAnnotationDefault ( MethodWrapper mw )
{
MethodWrapper [ ] methods = GetMethods ( ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] = = mw )
{
2006-04-19 19:49:54 +04:00
object defVal = impl . GetMethodDefaultValue ( i ) ;
if ( defVal ! = null )
{
2007-12-19 14:28:09 +03:00
return JVM . NewAnnotationElementValue ( mw . DeclaringType . GetClassLoader ( ) . GetJavaClassLoader ( ) , mw . ReturnType . ClassObject , defVal ) ;
2006-04-19 19:49:54 +04:00
}
return null ;
2005-11-01 17:01:42 +03:00
}
}
Debug . Fail ( "Unreachable code" ) ;
return null ;
}
2006-04-10 13:09:09 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#endif // !COMPACT_FRAMEWORK
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
class CompiledTypeWrapper : TypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private TypeWrapper [ ] interfaces ;
private TypeWrapper [ ] innerclasses ;
2005-08-24 12:14:23 +04:00
private MethodInfo clinitMethod ;
2007-09-19 13:38:05 +04:00
private Modifiers reflectiveModifiers ;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal static CompiledTypeWrapper newInstance ( string name , Type type )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO since ghost and remapped types can only exist in the core library assembly, we probably
// should be able to remove the Type.IsDefined() tests in most cases
2005-12-07 12:06:32 +03:00
if ( type . IsValueType & & AttributeHelper . IsGhostInterface ( type ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return new CompiledGhostTypeWrapper ( name , type ) ;
}
2005-12-07 12:06:32 +03:00
else if ( AttributeHelper . IsRemappedType ( type ) )
2005-06-01 13:49:30 +04:00
{
return new CompiledRemappedTypeWrapper ( name , type ) ;
}
else
{
return new CompiledTypeWrapper ( name , type ) ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledRemappedTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type remappedType ;
internal CompiledRemappedTypeWrapper ( string name , Type type )
: base ( name , type )
2005-03-23 12:33:18 +03:00
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper . GetRemappedType ( type ) ;
if ( attr = = null )
2005-06-01 13:49:30 +04:00
{
throw new InvalidOperationException ( ) ;
}
2005-12-07 12:06:32 +03:00
remappedType = attr . Type ;
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return remappedType ;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return true ;
}
}
protected override void LazyPublishMembers ( )
{
2008-08-15 16:01:06 +04:00
List < MethodWrapper > methods = new List < MethodWrapper > ( ) ;
List < FieldWrapper > fields = new List < FieldWrapper > ( ) ;
2007-11-26 11:38:38 +03:00
MemberInfo [ ] members = type . GetMembers ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
2005-06-01 13:49:30 +04:00
foreach ( MemberInfo m in members )
{
if ( ! AttributeHelper . IsHideFromJava ( m ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase ;
if ( method ! = null & &
( remappedType . IsSealed | | ! m . Name . StartsWith ( "instancehelper_" ) ) & &
( ! remappedType . IsSealed | | method . IsStatic ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
methods . Add ( CreateRemappedMethodWrapper ( method ) ) ;
}
else
{
FieldInfo field = m as FieldInfo ;
if ( field ! = null )
{
fields . Add ( CreateFieldWrapper ( field ) ) ;
}
2005-03-23 12:33:18 +03:00
}
}
}
2005-06-01 13:49:30 +04:00
// if we're a remapped interface, we need to get the methods from the real interface
if ( remappedType . IsInterface )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
Type nestedHelper = type . GetNestedType ( "__Helper" , BindingFlags . Public | BindingFlags . Static ) ;
2005-12-07 12:06:32 +03:00
foreach ( RemappedInterfaceMethodAttribute m in AttributeHelper . GetRemappedInterfaceMethods ( type ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo method = remappedType . GetMethod ( m . MappedTo ) ;
MethodInfo mbHelper = method ;
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( method , false ) ;
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
2008-05-31 19:20:29 +04:00
MemberFlags flags = MemberFlags . None ;
GetNameSigFromMethodBase ( method , out name , out sig , out retType , out paramTypes , ref flags ) ;
2005-06-01 13:49:30 +04:00
if ( nestedHelper ! = null )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
mbHelper = nestedHelper . GetMethod ( m . Name ) ;
if ( mbHelper = = null )
{
mbHelper = method ;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
methods . Add ( new CompiledRemappedMethodWrapper ( this , m . Name , sig , method , retType , paramTypes , modifiers , false , mbHelper , null ) ) ;
2005-03-23 12:33:18 +03:00
}
}
2008-08-15 16:01:06 +04:00
SetMethods ( methods . ToArray ( ) ) ;
SetFields ( fields . ToArray ( ) ) ;
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
private MethodWrapper CreateRemappedMethodWrapper ( MethodBase mb )
2005-03-23 12:33:18 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( mb , false ) ;
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
2008-05-31 19:20:29 +04:00
MemberFlags flags = MemberFlags . None ;
GetNameSigFromMethodBase ( mb , out name , out sig , out retType , out paramTypes , ref flags ) ;
2005-06-01 13:49:30 +04:00
MethodInfo mbHelper = mb as MethodInfo ;
2006-04-05 12:18:58 +04:00
bool hideFromReflection = mbHelper ! = null & & AttributeHelper . IsHideFromReflection ( mbHelper ) ;
2005-06-01 13:49:30 +04:00
MethodInfo mbNonvirtualHelper = null ;
if ( ! mb . IsStatic & & ! mb . IsConstructor )
{
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
Type [ ] argTypes = new Type [ parameters . Length + 1 ] ;
argTypes [ 0 ] = remappedType ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
argTypes [ i + 1 ] = parameters [ i ] . ParameterType ;
}
MethodInfo helper = type . GetMethod ( "instancehelper_" + mb . Name , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Static , null , argTypes , null ) ;
if ( helper ! = null )
{
mbHelper = helper ;
}
mbNonvirtualHelper = type . GetMethod ( "nonvirtualhelper/" + mb . Name , BindingFlags . NonPublic | BindingFlags . Static , null , argTypes , null ) ;
2005-03-23 12:33:18 +03:00
}
2006-04-05 12:18:58 +04:00
return new CompiledRemappedMethodWrapper ( this , name , sig , mb , retType , paramTypes , modifiers , hideFromReflection , mbHelper , mbNonvirtualHelper ) ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledGhostTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private FieldInfo ghostRefField ;
private Type typeAsBaseType ;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal CompiledGhostTypeWrapper ( string name , Type type )
: base ( name , type )
{
}
internal override Type TypeAsBaseType
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( typeAsBaseType = = null )
{
typeAsBaseType = type . GetNestedType ( "__Interface" ) ;
}
return typeAsBaseType ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo GhostRefField
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ghostRefField = = null )
{
ghostRefField = type . GetField ( "__<ref>" ) ;
}
return ghostRefField ;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override bool IsGhost
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return true ;
}
2005-03-23 12:33:18 +03:00
}
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
internal static string GetName ( Type type )
2002-12-18 19:00:25 +03:00
{
2008-04-22 10:24:55 +04:00
Debug . Assert ( ! type . IsGenericType ) ;
2005-12-07 12:06:32 +03:00
Debug . Assert ( AttributeHelper . IsJavaModule ( type . Module ) ) ;
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// look for our custom attribute, that contains the real name of the type (for inner classes)
2005-12-07 12:06:32 +03:00
InnerClassAttribute attr = AttributeHelper . GetInnerClass ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string name = attr . InnerClassName ;
2005-07-07 15:24:08 +04:00
if ( name ! = null )
{
return name ;
}
2006-05-15 13:08:01 +04:00
if ( type . DeclaringType ! = null )
{
return GetName ( type . DeclaringType ) + "$" + type . Name ;
}
2005-06-01 13:49:30 +04:00
}
return type . FullName ;
2003-08-13 19:00:41 +04:00
}
2005-06-01 13:49:30 +04:00
// TODO consider resolving the baseType lazily
private static TypeWrapper GetBaseTypeWrapper ( Type type )
2003-08-13 19:00:41 +04:00
{
2005-12-07 12:06:32 +03:00
if ( type . IsInterface | | AttributeHelper . IsGhostInterface ( type ) )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return null ;
}
else if ( type . BaseType = = null )
{
// System.Object must appear to be derived from java.lang.Object
return CoreClasses . java . lang . Object . Wrapper ;
}
else
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper . GetRemappedType ( type ) ;
if ( attr ! = null )
2004-03-08 18:18:47 +03:00
{
2005-12-07 12:06:32 +03:00
if ( attr . Type = = typeof ( object ) )
2005-06-01 13:49:30 +04:00
{
return null ;
}
else
{
return CoreClasses . java . lang . Object . Wrapper ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetWrapperFromType ( type . BaseType ) ;
2004-03-08 18:18:47 +03:00
}
2003-08-13 19:00:41 +04:00
}
2002-12-18 19:00:25 +03:00
2006-04-05 12:18:58 +04:00
private CompiledTypeWrapper ( ExModifiers exmod , string name , TypeWrapper baseTypeWrapper )
: base ( exmod . Modifiers , name , baseTypeWrapper )
{
this . IsInternal = exmod . IsInternal ;
}
2005-06-01 13:49:30 +04:00
private CompiledTypeWrapper ( string name , Type type )
2006-04-05 12:18:58 +04:00
: this ( GetModifiers ( type ) , name , GetBaseTypeWrapper ( type ) )
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type is TypeBuilder ) ) ;
2007-01-16 13:14:47 +03:00
Debug . Assert ( ! type . Name . EndsWith ( "[]" ) ) ;
2005-06-01 13:49:30 +04:00
this . type = type ;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader ( )
{
2006-05-15 13:08:01 +04:00
return ClassLoaderWrapper . GetAssemblyClassLoader ( type . Assembly ) ;
2006-03-23 14:57:41 +03:00
}
2006-04-05 12:18:58 +04:00
private static ExModifiers GetModifiers ( Type type )
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
ModifiersAttribute attr = AttributeHelper . GetModifiersAttribute ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
return new ExModifiers ( attr . Modifiers , attr . IsInternal ) ;
2005-06-01 13:49:30 +04:00
}
// only returns public, protected, private, final, static, abstract and interface (as per
// the documentation of Class.getModifiers())
Modifiers modifiers = 0 ;
if ( type . IsPublic )
{
modifiers | = Modifiers . Public ;
}
// TODO do we really need to look for nested attributes? I think all inner classes will have the ModifiersAttribute.
else if ( type . IsNestedPublic )
{
modifiers | = Modifiers . Public | Modifiers . Static ;
}
else if ( type . IsNestedPrivate )
{
modifiers | = Modifiers . Private | Modifiers . Static ;
}
else if ( type . IsNestedFamily | | type . IsNestedFamORAssem )
{
modifiers | = Modifiers . Protected | Modifiers . Static ;
}
else if ( type . IsNestedAssembly | | type . IsNestedFamANDAssem )
{
modifiers | = Modifiers . Static ;
}
if ( type . IsSealed )
{
modifiers | = Modifiers . Final ;
}
if ( type . IsAbstract )
{
modifiers | = Modifiers . Abstract ;
}
if ( type . IsInterface )
{
modifiers | = Modifiers . Interface ;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers ( modifiers , false ) ;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2005-08-24 12:14:23 +04:00
// trigger LazyPublishMembers
GetMethods ( ) ;
return clinitMethod ! = null ;
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if ( interfaces = = null )
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE instead of getting the interfaces list from Type, we use a custom
// attribute to list the implemented interfaces, because Java reflection only
// reports the interfaces *directly* implemented by the type, not the inherited
// interfaces. This is significant for serialVersionUID calculation (for example).
2005-12-07 12:06:32 +03:00
ImplementsAttribute attr = AttributeHelper . GetImplements ( type ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string [ ] interfaceNames = attr . Interfaces ;
2005-06-01 13:49:30 +04:00
TypeWrapper [ ] interfaceWrappers = new TypeWrapper [ interfaceNames . Length ] ;
for ( int i = 0 ; i < interfaceWrappers . Length ; i + + )
{
interfaceWrappers [ i ] = GetClassLoader ( ) . LoadClassByDottedName ( interfaceNames [ i ] ) ;
}
this . interfaces = interfaceWrappers ;
}
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
interfaces = TypeWrapper . EmptyArray ;
2004-05-14 13:31:54 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return interfaces ;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO why are we caching this?
if ( innerclasses = = null )
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type [ ] nestedTypes = type . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . DeclaredOnly ) ;
2008-08-15 16:01:06 +04:00
List < TypeWrapper > wrappers = new List < TypeWrapper > ( ) ;
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < nestedTypes . Length ; i + + )
2003-10-17 12:08:31 +04:00
{
2008-11-03 09:48:05 +03:00
if ( ! AttributeHelper . IsHideFromJava ( nestedTypes [ i ] ) & & ! nestedTypes [ i ] . Name . StartsWith ( "__<" ) )
2005-06-01 13:49:30 +04:00
{
wrappers . Add ( ClassLoaderWrapper . GetWrapperFromType ( nestedTypes [ i ] ) ) ;
}
2003-10-17 12:08:31 +04:00
}
2007-10-10 09:31:57 +04:00
foreach ( string s in AttributeHelper . GetNonNestedInnerClasses ( type ) )
{
wrappers . Add ( GetClassLoader ( ) . LoadClassByDottedName ( s ) ) ;
}
2008-08-15 16:01:06 +04:00
innerclasses = wrappers . ToArray ( ) ;
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
return innerclasses ;
2003-02-18 12:30:34 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type declaringType = type . DeclaringType ;
if ( declaringType ! = null )
{
return ClassLoaderWrapper . GetWrapperFromType ( declaringType ) ;
}
2007-10-10 09:31:57 +04:00
string decl = AttributeHelper . GetNonNestedOuterClasses ( type ) ;
if ( decl ! = null )
{
return GetClassLoader ( ) . LoadClassByDottedName ( decl ) ;
}
2005-06-01 13:49:30 +04:00
return null ;
2003-02-20 17:18:38 +03:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-05-30 16:08:59 +04:00
{
2007-09-19 13:38:05 +04:00
if ( reflectiveModifiers = = 0 )
2005-06-01 13:49:30 +04:00
{
2007-09-19 13:38:05 +04:00
InnerClassAttribute attr = AttributeHelper . GetInnerClass ( type ) ;
if ( attr ! = null )
{
reflectiveModifiers = attr . Modifiers ;
}
else
{
reflectiveModifiers = Modifiers ;
}
2005-06-01 13:49:30 +04:00
}
2007-09-19 13:38:05 +04:00
return reflectiveModifiers ;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsBaseType
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private void SigTypePatchUp ( string sigtype , ref TypeWrapper type )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( sigtype ! = type . SigName )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// if type is an array, we know that it is a ghost array, because arrays of unloadable are compiled
// as object (not as arrays of object)
if ( type . IsArray )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
type = GetClassLoader ( ) . FieldTypeWrapperFromSig ( sigtype ) ;
}
2006-10-04 13:03:18 +04:00
else if ( type . IsPrimitive )
{
type = DotNetTypeWrapper . GetWrapperFromDotNetType ( type . TypeAsTBD ) ;
if ( sigtype ! = type . SigName )
{
throw new InvalidOperationException ( ) ;
}
}
else if ( type . IsNonPrimitiveValueType )
{
// this can't happen and even if it does happen we cannot return
// UnloadableTypeWrapper because that would result in incorrect code
// being generated
throw new InvalidOperationException ( ) ;
}
2005-06-01 13:49:30 +04:00
else
{
if ( sigtype [ 0 ] = = 'L' )
{
sigtype = sigtype . Substring ( 1 , sigtype . Length - 2 ) ;
}
2006-10-04 13:03:18 +04:00
try
{
TypeWrapper tw = GetClassLoader ( ) . LoadClassByDottedNameFast ( sigtype ) ;
if ( tw ! = null & & tw . IsRemapped )
{
type = tw ;
return ;
}
}
catch ( RetargetableJavaException )
{
}
2005-06-01 13:49:30 +04:00
type = new UnloadableTypeWrapper ( sigtype ) ;
2004-08-17 13:05:21 +04:00
}
2003-05-30 16:08:59 +04:00
}
}
2005-06-01 13:49:30 +04:00
private static void ParseSig ( string sig , out string [ ] sigparam , out string sigret )
2003-10-17 12:08:31 +04:00
{
2008-08-15 16:01:06 +04:00
List < string > list = new List < string > ( ) ;
2005-06-01 13:49:30 +04:00
int pos = 1 ;
for ( ; ; )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
switch ( sig [ pos ] )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
case 'L' :
2004-08-17 13:05:21 +04:00
{
int end = sig . IndexOf ( ';' , pos ) + 1 ;
list . Add ( sig . Substring ( pos , end - pos ) ) ;
pos = end ;
2005-06-01 13:49:30 +04:00
break ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case '[' :
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
int skip = 1 ;
while ( sig [ pos + skip ] = = '[' ) skip + + ;
if ( sig [ pos + skip ] = = 'L' )
{
int end = sig . IndexOf ( ';' , pos ) + 1 ;
list . Add ( sig . Substring ( pos , end - pos ) ) ;
pos = end ;
}
else
{
skip + + ;
list . Add ( sig . Substring ( pos , skip ) ) ;
pos + = skip ;
}
break ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case ')' :
2008-08-15 16:01:06 +04:00
sigparam = list . ToArray ( ) ;
2005-06-01 13:49:30 +04:00
sigret = sig . Substring ( pos + 1 ) ;
return ;
default :
list . Add ( sig . Substring ( pos , 1 ) ) ;
pos + + ;
break ;
2003-10-17 12:08:31 +04:00
}
}
}
2008-05-31 19:20:29 +04:00
private void GetNameSigFromMethodBase ( MethodBase method , out string name , out string sig , out TypeWrapper retType , out TypeWrapper [ ] paramTypes , ref MemberFlags flags )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
retType = method is ConstructorInfo ? PrimitiveTypeWrapper . VOID : ClassLoaderWrapper . GetWrapperFromType ( ( ( MethodInfo ) method ) . ReturnType ) ;
ParameterInfo [ ] parameters = method . GetParameters ( ) ;
2008-05-31 19:20:29 +04:00
int len = parameters . Length ;
if ( len > 0
& & parameters [ len - 1 ] . ParameterType = = CoreClasses . ikvm . @internal . CallerID . Wrapper . TypeAsSignatureType
& & ! method . DeclaringType . IsInterface
2009-01-17 14:05:10 +03:00
& & GetClassLoader ( ) = = ClassLoaderWrapper . GetBootstrapClassLoader ( ) )
2008-05-31 19:20:29 +04:00
{
len - - ;
flags | = MemberFlags . CallerID ;
}
paramTypes = new TypeWrapper [ len ] ;
for ( int i = 0 ; i < len ; i + + )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
paramTypes [ i ] = ClassLoaderWrapper . GetWrapperFromType ( parameters [ i ] . ParameterType ) ;
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper . GetNameSig ( method ) ;
if ( attr ! = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
name = attr . Name ;
sig = attr . Sig ;
string [ ] sigparams ;
string sigret ;
ParseSig ( sig , out sigparams , out sigret ) ;
// HACK newhelper methods have a return type, but it should be void
if ( name = = "<init>" )
{
retType = PrimitiveTypeWrapper . VOID ;
}
SigTypePatchUp ( sigret , ref retType ) ;
// if we have a remapped method, the paramTypes array contains an additional entry for "this" so we have
// to remove that
if ( paramTypes . Length = = sigparams . Length + 1 )
{
TypeWrapper [ ] temp = paramTypes ;
paramTypes = new TypeWrapper [ sigparams . Length ] ;
Array . Copy ( temp , 1 , paramTypes , 0 , paramTypes . Length ) ;
}
Debug . Assert ( sigparams . Length = = paramTypes . Length ) ;
for ( int i = 0 ; i < sigparams . Length ; i + + )
{
SigTypePatchUp ( sigparams [ i ] , ref paramTypes [ i ] ) ;
}
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
if ( method is ConstructorInfo )
{
name = method . IsStatic ? "<clinit>" : "<init>" ;
}
else
{
name = method . Name ;
}
System . Text . StringBuilder sb = new System . Text . StringBuilder ( "(" ) ;
foreach ( TypeWrapper tw in paramTypes )
{
sb . Append ( tw . SigName ) ;
}
sb . Append ( ")" ) ;
sb . Append ( retType . SigName ) ;
sig = sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2003-10-17 12:08:31 +04:00
}
2009-03-06 08:33:08 +03:00
private sealed class DelegateConstructorMethodWrapper : MethodWrapper
{
private readonly ConstructorInfo constructor ;
2009-03-06 09:43:40 +03:00
private MethodInfo invoke ;
2009-03-06 08:33:08 +03:00
private DelegateConstructorMethodWrapper ( TypeWrapper tw , TypeWrapper iface , ExModifiers mods )
: base ( tw , StringConstants . INIT , "(" + iface . SigName + ")V" , null , PrimitiveTypeWrapper . VOID , new TypeWrapper [ ] { iface } , mods . Modifiers , mods . IsInternal ? MemberFlags . InternalAccess : MemberFlags . None )
{
}
internal DelegateConstructorMethodWrapper ( TypeWrapper tw , MethodBase method )
: this ( tw , tw . GetClassLoader ( ) . LoadClassByDottedName ( tw . Name + DotNetTypeWrapper . DelegateInterfaceSuffix ) , AttributeHelper . GetModifiers ( method , false ) )
{
constructor = ( ConstructorInfo ) method ;
}
2009-03-06 09:43:40 +03:00
protected override void DoLinkMethod ( )
2009-03-06 08:33:08 +03:00
{
MethodWrapper mw = GetParameters ( ) [ 0 ] . GetMethods ( ) [ 0 ] ;
mw . Link ( ) ;
2009-03-06 09:43:40 +03:00
invoke = ( MethodInfo ) mw . GetMethod ( ) ;
}
internal override void EmitNewobj ( CodeEmitter ilgen , MethodAnalyzer ma , int opcodeIndex )
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Ldvirtftn , invoke ) ;
2009-03-06 08:33:08 +03:00
ilgen . Emit ( OpCodes . Newobj , constructor ) ;
}
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
2004-03-08 18:18:47 +03:00
{
2009-03-06 08:33:08 +03:00
bool isDelegate = type . BaseType = = typeof ( MulticastDelegate ) ;
2005-08-24 12:14:23 +04:00
clinitMethod = type . GetMethod ( "__<clinit>" , BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ) ;
2008-08-15 16:01:06 +04:00
List < MethodWrapper > methods = new List < MethodWrapper > ( ) ;
List < FieldWrapper > fields = new List < FieldWrapper > ( ) ;
2007-11-26 11:38:38 +03:00
MemberInfo [ ] members = type . GetMembers ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
2005-06-01 13:49:30 +04:00
foreach ( MemberInfo m in members )
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! AttributeHelper . IsHideFromJava ( m ) )
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase ;
if ( method ! = null )
2004-07-10 11:19:42 +04:00
{
2005-08-24 12:14:23 +04:00
if ( method . IsSpecialName & &
( method . Name = = "op_Implicit" | | method . Name . StartsWith ( "__<" ) ) )
2005-07-07 18:03:21 +04:00
{
// skip
}
2009-03-06 08:33:08 +03:00
else if ( isDelegate & & method . IsConstructor & & ! method . IsStatic )
{
methods . Add ( new DelegateConstructorMethodWrapper ( this , method ) ) ;
}
2005-07-07 18:03:21 +04:00
else
{
string name ;
string sig ;
TypeWrapper retType ;
TypeWrapper [ ] paramTypes ;
MethodInfo mi = method as MethodInfo ;
2005-08-14 19:49:50 +04:00
bool hideFromReflection = mi ! = null ? AttributeHelper . IsHideFromReflection ( mi ) : false ;
MemberFlags flags = hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None ;
2008-05-31 19:20:29 +04:00
GetNameSigFromMethodBase ( method , out name , out sig , out retType , out paramTypes , ref flags ) ;
2006-04-05 12:18:58 +04:00
ExModifiers mods = AttributeHelper . GetModifiers ( method , false ) ;
if ( mods . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
methods . Add ( MethodWrapper . Create ( this , name , sig , method , retType , paramTypes , mods . Modifiers , flags ) ) ;
2005-07-07 18:03:21 +04:00
}
2005-06-01 13:49:30 +04:00
}
else
{
FieldInfo field = m as FieldInfo ;
if ( field ! = null )
{
2005-07-07 18:03:21 +04:00
if ( field . IsSpecialName & & field . Name . StartsWith ( "__<" ) )
{
// skip
}
else
{
fields . Add ( CreateFieldWrapper ( field ) ) ;
}
2005-06-01 13:49:30 +04:00
}
2005-08-14 19:49:50 +04:00
else
{
2006-09-26 08:53:16 +04:00
// NOTE explictly defined properties (in map.xml) are decorated with HideFromJava,
// so we don't need to worry about them here
2005-08-14 19:49:50 +04:00
PropertyInfo property = m as PropertyInfo ;
if ( property ! = null )
{
// Only AccessStub properties (marked by HideFromReflectionAttribute)
// are considered here
if ( AttributeHelper . IsHideFromReflection ( property ) )
{
fields . Add ( new CompiledAccessStubFieldWrapper ( this , property ) ) ;
}
2006-08-15 12:50:43 +04:00
else
{
2008-04-14 09:13:41 +04:00
// If the property has a ModifiersAttribute, we know that it is an explicit property
// (defined in Java source by an @ikvm.lang.Property annotation)
ModifiersAttribute mods = AttributeHelper . GetModifiersAttribute ( property ) ;
if ( mods ! = null )
{
fields . Add ( new CompiledPropertyFieldWrapper ( this , property , new ExModifiers ( mods . Modifiers , mods . IsInternal ) ) ) ;
}
else
{
fields . Add ( CreateFieldWrapper ( property ) ) ;
}
2006-08-15 12:50:43 +04:00
}
2005-08-14 19:49:50 +04:00
}
}
2004-07-10 11:19:42 +04:00
}
2004-03-08 18:18:47 +03:00
}
}
2008-08-15 16:01:06 +04:00
SetMethods ( methods . ToArray ( ) ) ;
SetFields ( fields . ToArray ( ) ) ;
2004-03-08 18:18:47 +03:00
}
2004-06-14 14:36:38 +04:00
2008-08-25 08:16:59 +04:00
private class CompiledRemappedMethodWrapper : SmartMethodWrapper
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodInfo mbHelper ;
2008-05-20 11:43:42 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private MethodInfo mbNonvirtualHelper ;
2008-05-20 11:43:42 +04:00
#endif
2004-06-14 14:36:38 +04:00
2006-04-05 12:18:58 +04:00
internal CompiledRemappedMethodWrapper ( TypeWrapper declaringType , string name , string sig , MethodBase method , TypeWrapper returnType , TypeWrapper [ ] parameterTypes , ExModifiers modifiers , bool hideFromReflection , MethodInfo mbHelper , MethodInfo mbNonvirtualHelper )
: base ( declaringType , name , sig , method , returnType , parameterTypes , modifiers . Modifiers ,
( modifiers . IsInternal ? MemberFlags . InternalAccess : MemberFlags . None ) | ( hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None ) )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
this . mbHelper = mbHelper ;
2008-05-20 11:43:42 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
this . mbNonvirtualHelper = mbNonvirtualHelper ;
2008-05-20 11:43:42 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
protected override void CallImpl ( CodeEmitter ilgen )
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
{
ilgen . Emit ( OpCodes . Call , mi ) ;
}
else
{
ilgen . Emit ( OpCodes . Call , ( ConstructorInfo ) mb ) ;
}
2004-06-14 14:36:38 +04:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
protected override void CallvirtImpl ( CodeEmitter ilgen )
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! mbHelper . IsStatic | | mbHelper . Name . StartsWith ( "instancehelper_" ) | | mbHelper . DeclaringType . Name = = "__Helper" ) ;
2006-11-20 12:21:38 +03:00
if ( mbHelper . IsPublic )
{
ilgen . Emit ( mbHelper . IsStatic ? OpCodes . Call : OpCodes . Callvirt , mbHelper ) ;
}
else
{
// HACK the helper is not public, this means that we're dealing with finalize or clone
ilgen . Emit ( OpCodes . Callvirt , ( MethodInfo ) GetMethod ( ) ) ;
}
2004-06-14 14:36:38 +04:00
}
2004-08-17 13:05:21 +04:00
2008-06-03 16:10:07 +04:00
protected override void NewobjImpl ( CodeEmitter ilgen )
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( mi . Name = = "newhelper" ) ;
ilgen . Emit ( OpCodes . Call , mi ) ;
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-07-02 18:50:35 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Newobj , ( ConstructorInfo ) mb ) ;
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2008-05-31 19:20:29 +04:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
2008-08-25 08:16:59 +04:00
protected override object InvokeNonvirtualRemapped ( object obj , object [ ] args )
2005-06-01 13:49:30 +04:00
{
2008-08-25 08:16:59 +04:00
Type [ ] p1 = GetParametersForDefineMethod ( ) ;
Type [ ] argTypes = new Type [ p1 . Length + 1 ] ;
p1 . CopyTo ( argTypes , 1 ) ;
argTypes [ 0 ] = this . DeclaringType . TypeAsSignatureType ;
MethodInfo mi = mbNonvirtualHelper ;
if ( mi = = null )
2004-03-08 18:18:47 +03:00
{
2008-08-25 08:16:59 +04:00
mi = mbHelper ;
2004-03-08 18:18:47 +03:00
}
2008-08-25 08:16:59 +04:00
object [ ] args1 = new object [ args . Length + 1 ] ;
args1 [ 0 ] = obj ;
args . CopyTo ( args1 , 1 ) ;
return mi . Invoke ( null , args1 ) ;
}
internal override void EmitCallvirtReflect ( CodeEmitter ilgen )
{
MethodBase mb = mbHelper ! = null ? mbHelper : GetMethod ( ) ;
ilgen . Emit ( mb . IsStatic ? OpCodes . Call : OpCodes . Callvirt , ( MethodInfo ) mb ) ;
2004-03-08 18:18:47 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-10-01 15:16:11 +04:00
internal string GetGenericSignature ( )
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper . GetSignature ( mbHelper ! = null ? mbHelper : GetMethod ( ) ) ;
if ( attr ! = null )
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr . Signature ;
2005-10-01 15:16:11 +04:00
}
return null ;
}
2004-10-04 23:30:53 +04:00
}
2004-01-28 14:28:16 +03:00
2006-08-15 12:50:43 +04:00
private FieldWrapper CreateFieldWrapper ( PropertyInfo prop )
{
MethodInfo getter = prop . GetGetMethod ( true ) ;
ExModifiers modifiers = AttributeHelper . GetModifiers ( getter , false ) ;
2006-08-17 12:14:47 +04:00
// for static methods AttributeHelper.GetModifiers won't set the Final flag
modifiers = new ExModifiers ( modifiers . Modifiers | Modifiers . Final , modifiers . IsInternal ) ;
2006-08-15 12:50:43 +04:00
string name = prop . Name ;
TypeWrapper type = ClassLoaderWrapper . GetWrapperFromType ( prop . PropertyType ) ;
NameSigAttribute attr = AttributeHelper . GetNameSig ( getter ) ;
if ( attr ! = null )
{
name = attr . Name ;
SigTypePatchUp ( attr . Sig , ref type ) ;
}
return new GetterFieldWrapper ( this , type , null , name , type . SigName , modifiers , getter , prop ) ;
}
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapper ( FieldInfo field )
2002-12-18 19:00:25 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper . GetModifiers ( field , false ) ;
2005-06-01 13:49:30 +04:00
string name = field . Name ;
TypeWrapper type = ClassLoaderWrapper . GetWrapperFromType ( field . FieldType ) ;
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper . GetNameSig ( field ) ;
if ( attr ! = null )
2005-06-01 13:49:30 +04:00
{
name = attr . Name ;
SigTypePatchUp ( attr . Sig , ref type ) ;
}
2002-12-18 19:00:25 +03:00
2006-08-15 12:50:43 +04:00
if ( field . IsLiteral )
2005-06-01 13:49:30 +04:00
{
2006-10-10 20:24:48 +04:00
MemberFlags flags = MemberFlags . None ;
2005-08-14 19:49:50 +04:00
if ( AttributeHelper . IsHideFromReflection ( field ) )
{
flags | = MemberFlags . HideFromReflection ;
}
2006-04-05 12:18:58 +04:00
if ( modifiers . IsInternal )
{
flags | = MemberFlags . InternalAccess ;
}
return new ConstantFieldWrapper ( this , type , name , type . SigName , modifiers . Modifiers , field , null , flags ) ;
2005-06-01 13:49:30 +04:00
}
else
{
return FieldWrapper . Create ( this , type , field , name , type . SigName , modifiers ) ;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2002-12-18 19:00:25 +03:00
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsMapUnsafeException
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-07-10 11:19:42 +04:00
{
2005-12-07 12:06:32 +03:00
return AttributeHelper . IsExceptionIsUnsafeForMapping ( type ) ;
2004-07-10 11:19:42 +04:00
}
2003-02-22 15:28:12 +03:00
}
2003-10-22 20:34:22 +04:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-10-22 20:34:22 +04:00
{
2006-03-01 15:26:25 +03:00
if ( BaseTypeWrapper ! = null )
{
BaseTypeWrapper . Finish ( ) ;
}
foreach ( TypeWrapper tw in this . Interfaces )
{
tw . Finish ( ) ;
}
2003-10-22 20:34:22 +04:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitRunClassConstructor ( CodeEmitter ilgen )
2005-08-24 12:14:23 +04:00
{
// trigger LazyPublishMembers
GetMethods ( ) ;
if ( clinitMethod ! = null )
{
ilgen . Emit ( OpCodes . Call , clinitMethod ) ;
}
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper . GetSignature ( type ) ;
if ( attr ! = null )
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr . Signature ;
2005-10-01 15:16:11 +04:00
}
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
if ( mw is CompiledRemappedMethodWrapper )
{
return ( ( CompiledRemappedMethodWrapper ) mw ) . GetGenericSignature ( ) ;
}
MethodBase mb = mw . GetMethod ( ) ;
if ( mb ! = null )
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper . GetSignature ( mb ) ;
if ( attr ! = null )
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr . Signature ;
2005-10-01 15:16:11 +04:00
}
}
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
FieldInfo fi = fw . GetField ( ) ;
if ( fi ! = null )
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper . GetSignature ( fi ) ;
if ( attr ! = null )
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr . Signature ;
2005-10-01 15:16:11 +04:00
}
}
2006-10-04 13:03:18 +04:00
else
{
GetterFieldWrapper getter = fw as GetterFieldWrapper ;
if ( getter ! = null )
{
SignatureAttribute attr = AttributeHelper . GetSignature ( getter . GetGetter ( ) ) ;
if ( attr ! = null )
{
return attr . Signature ;
}
}
}
2005-10-01 15:16:11 +04:00
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
2009-02-04 09:51:40 +03:00
EnclosingMethodAttribute enc = AttributeHelper . GetEnclosingMethodAttribute ( type ) ;
if ( enc ! = null )
2005-10-01 15:16:11 +04:00
{
return new string [ ] { enc . ClassName , enc . MethodName , enc . MethodSignature } ;
}
return null ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
2007-03-13 10:44:23 +03:00
if ( type . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
2005-11-01 17:01:42 +03:00
return type . GetCustomAttributes ( false ) ;
}
2006-04-20 11:30:59 +04:00
internal override object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
2007-03-13 10:44:23 +03:00
MethodBase mb = mw . GetMethod ( ) ;
if ( mb . DeclaringType . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
return mb . GetCustomAttributes ( false ) ;
2006-04-20 11:30:59 +04:00
}
internal override object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
2007-03-13 10:44:23 +03:00
MethodBase mb = mw . GetMethod ( ) ;
if ( mb . DeclaringType . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
2007-06-14 10:41:37 +04:00
int skip = 0 ;
if ( mb . IsStatic & & ! mw . IsStatic & & mw . Name ! = "<init>" )
{
skip = 1 ;
}
2008-06-13 11:52:55 +04:00
int skipEnd = 0 ;
if ( mw . HasCallerID )
{
skipEnd = 1 ;
}
object [ ] [ ] attribs = new object [ parameters . Length - skip - skipEnd ] [ ] ;
for ( int i = skip ; i < parameters . Length - skipEnd ; i + + )
2006-04-20 11:30:59 +04:00
{
2007-06-14 10:41:37 +04:00
attribs [ i - skip ] = parameters [ i ] . GetCustomAttributes ( false ) ;
2006-04-20 11:30:59 +04:00
}
return attribs ;
}
internal override object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
2006-10-04 13:03:18 +04:00
FieldInfo field = fw . GetField ( ) ;
if ( field ! = null )
{
2007-03-13 10:44:23 +03:00
if ( field . DeclaringType . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
2006-10-04 13:03:18 +04:00
return field . GetCustomAttributes ( false ) ;
}
GetterFieldWrapper getter = fw as GetterFieldWrapper ;
if ( getter ! = null )
{
2007-03-13 10:44:23 +03:00
if ( getter . GetGetter ( ) . DeclaringType . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
2006-10-04 13:03:18 +04:00
return getter . GetGetter ( ) . GetCustomAttributes ( false ) ;
}
2008-04-14 09:13:41 +04:00
CompiledPropertyFieldWrapper prop = fw as CompiledPropertyFieldWrapper ;
if ( prop ! = null )
{
if ( prop . GetProperty ( ) . DeclaringType . Assembly . ReflectionOnly )
{
// TODO on Whidbey this must be implemented
return null ;
}
return prop . GetProperty ( ) . GetCustomAttributes ( false ) ;
}
2006-10-04 13:03:18 +04:00
return new object [ 0 ] ;
2006-04-20 11:30:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
private class CompiledAnnotation : Annotation
{
private Type type ;
internal CompiledAnnotation ( Type type )
{
this . type = type ;
}
2006-04-20 11:30:59 +04:00
private CustomAttributeBuilder MakeCustomAttributeBuilder ( object annotation )
{
return new CustomAttributeBuilder ( type . GetConstructor ( new Type [ ] { typeof ( object [ ] ) } ) , new object [ ] { annotation } ) ;
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation )
2005-11-01 17:01:42 +03:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-04-20 11:30:59 +04:00
tb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation )
2006-04-20 11:30:59 +04:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-04-20 11:30:59 +04:00
cb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation )
2006-04-20 11:30:59 +04:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-04-20 11:30:59 +04:00
mb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation )
2006-04-20 11:30:59 +04:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-04-20 11:30:59 +04:00
fb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation )
2006-04-20 11:30:59 +04:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-04-20 11:30:59 +04:00
pb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
2005-11-01 17:01:42 +03:00
}
2006-06-20 18:31:56 +04:00
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation )
2006-06-20 18:31:56 +04:00
{
2008-02-09 20:37:38 +03:00
annotation = QualifyClassNames ( loader , annotation ) ;
2006-06-20 18:31:56 +04:00
ab . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2008-04-14 09:13:41 +04:00
internal override void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation )
{
annotation = QualifyClassNames ( loader , annotation ) ;
pb . SetCustomAttribute ( MakeCustomAttributeBuilder ( annotation ) ) ;
}
2005-11-01 17:01:42 +03:00
}
internal override Annotation Annotation
{
get
{
2006-04-11 18:59:43 +04:00
string annotationAttribute = AttributeHelper . GetAnnotationAttributeType ( type ) ;
if ( annotationAttribute ! = null )
2005-11-01 17:01:42 +03:00
{
2006-04-11 18:59:43 +04:00
return new CompiledAnnotation ( type . Assembly . GetType ( annotationAttribute , true ) ) ;
2005-11-01 17:01:42 +03:00
}
return null ;
}
}
2006-05-04 12:09:56 +04:00
2006-12-28 10:46:21 +03:00
internal override Type EnumType
{
get
{
if ( ( this . Modifiers & Modifiers . Enum ) ! = 0 )
{
return type . GetNestedType ( "__Enum" ) ;
}
return null ;
}
}
2006-05-04 12:09:56 +04:00
internal override string GetSourceFileName ( )
{
object [ ] attr = type . GetCustomAttributes ( typeof ( SourceFileAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( SourceFileAttribute ) attr [ 0 ] ) . SourceFile ;
}
if ( type . Module . IsDefined ( typeof ( SourceFileAttribute ) , false ) )
{
return type . Name + ".java" ;
}
return null ;
}
internal override int GetSourceLineNumber ( MethodBase mb , int ilOffset )
{
object [ ] attr = mb . GetCustomAttributes ( typeof ( LineNumberTableAttribute ) , false ) ;
if ( attr . Length = = 1 )
{
return ( ( LineNumberTableAttribute ) attr [ 0 ] ) . GetLineNumber ( ilOffset ) ;
}
return - 1 ;
}
2005-12-07 12:06:32 +03:00
#endif
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sealed class DotNetTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private const string NamePrefix = "cli." ;
2005-08-25 13:36:36 +04:00
internal const string DelegateInterfaceSuffix = "$Method" ;
2006-06-15 16:29:11 +04:00
internal const string AttributeAnnotationSuffix = "$Annotation" ;
2007-04-15 12:01:19 +04:00
internal const string AttributeAnnotationReturnValueSuffix = "$__ReturnValue" ;
internal const string AttributeAnnotationMultipleSuffix = "$__Multiple" ;
2007-01-04 10:46:38 +03:00
internal const string EnumEnumSuffix = "$__Enum" ;
2008-03-03 10:05:19 +03:00
internal const string GenericEnumEnumTypeName = "ikvm.internal.EnumEnum`1" ;
internal const string GenericDelegateInterfaceTypeName = "ikvm.internal.DelegateInterface`1" ;
internal const string GenericAttributeAnnotationTypeName = "ikvm.internal.AttributeAnnotation`1" ;
internal const string GenericAttributeAnnotationReturnValueTypeName = "ikvm.internal.AttributeAnnotationReturnValue`1" ;
internal const string GenericAttributeAnnotationMultipleTypeName = "ikvm.internal.AttributeAnnotationMultiple`1" ;
2009-02-24 09:11:17 +03:00
private static readonly Dictionary < Type , TypeWrapper > types = new Dictionary < Type , TypeWrapper > ( ) ;
2005-06-01 13:49:30 +04:00
private readonly Type type ;
private TypeWrapper [ ] innerClasses ;
private TypeWrapper outerClass ;
private TypeWrapper [ ] interfaces ;
private static Modifiers GetModifiers ( Type type )
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
Modifiers modifiers = 0 ;
if ( type . IsPublic )
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Public ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedPublic )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Static ;
if ( IsVisible ( type ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Public ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedPrivate )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Private | Modifiers . Static ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( type . IsNestedFamily | | type . IsNestedFamORAssem )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers | = Modifiers . Protected | Modifiers . Static ;
}
else if ( type . IsNestedAssembly | | type . IsNestedFamANDAssem )
{
modifiers | = Modifiers . Static ;
2004-04-23 18:21:43 +04:00
}
2003-08-26 15:24:17 +04:00
2005-06-01 13:49:30 +04:00
if ( type . IsSealed )
{
modifiers | = Modifiers . Final ;
}
else if ( type . IsAbstract ) // we can't be abstract if we're final
{
modifiers | = Modifiers . Abstract ;
}
if ( type . IsInterface )
{
modifiers | = Modifiers . Interface ;
}
return modifiers ;
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
// NOTE when this is called on a remapped type, the "warped" underlying type name is returned.
// E.g. GetName(typeof(object)) returns "cli.System.Object".
internal static string GetName ( Type type )
2003-08-26 15:24:17 +04:00
{
2007-01-16 13:14:47 +03:00
Debug . Assert ( ! type . Name . EndsWith ( "[]" ) & & ! AttributeHelper . IsJavaModule ( type . Module ) ) ;
2003-08-26 15:24:17 +04:00
2006-01-23 13:18:44 +03:00
string name = type . FullName ;
if ( name = = null )
{
2006-07-26 11:57:18 +04:00
// generic type parameters don't have a full name
2006-01-23 13:18:44 +03:00
return null ;
}
2007-11-26 12:01:35 +03:00
if ( type . ContainsGenericParameters )
2006-07-26 11:57:18 +04:00
{
// open generic types are not visible
return null ;
}
2007-11-26 12:01:35 +03:00
if ( type . IsGenericType )
2006-07-26 11:57:18 +04:00
{
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
2007-11-26 12:01:35 +03:00
sb . Append ( MangleTypeName ( type . GetGenericTypeDefinition ( ) . FullName ) ) ;
2006-07-26 11:57:18 +04:00
sb . Append ( "_$$$_" ) ;
string sep = "" ;
2007-11-26 12:01:35 +03:00
foreach ( Type t1 in type . GetGenericArguments ( ) )
2006-07-26 11:57:18 +04:00
{
2007-05-27 12:16:58 +04:00
Type t = t1 ;
2006-07-26 11:57:18 +04:00
sb . Append ( sep ) ;
2007-05-27 12:16:58 +04:00
// NOTE we can't use ClassLoaderWrapper.GetWrapperFromType() here to get t's name,
// because we might be resolving a generic type that refers to a type that is in
// the process of being constructed.
/ /
// For example:
// class Base<T> { }
// class Derived : Base<Derived> { }
/ /
while ( ClassLoaderWrapper . IsVector ( t ) )
{
t = t . GetElementType ( ) ;
2006-07-26 11:57:18 +04:00
sb . Append ( 'A' ) ;
}
2007-05-27 12:16:58 +04:00
if ( PrimitiveTypeWrapper . IsPrimitiveType ( t ) )
2006-07-26 11:57:18 +04:00
{
2007-05-27 12:16:58 +04:00
sb . Append ( ClassLoaderWrapper . GetWrapperFromType ( t ) . SigName ) ;
2006-07-26 11:57:18 +04:00
}
else
{
2007-05-27 12:16:58 +04:00
string s ;
if ( ClassLoaderWrapper . IsRemappedType ( t ) )
{
s = ClassLoaderWrapper . GetWrapperFromType ( t ) . Name ;
}
2007-10-22 13:25:10 +04:00
else if ( ClassLoaderWrapper . IsDynamicType ( t ) | | AttributeHelper . IsJavaModule ( t . Module ) )
2007-05-27 12:16:58 +04:00
{
s = CompiledTypeWrapper . GetName ( t ) ;
}
else
{
s = DotNetTypeWrapper . GetName ( t ) ;
}
2007-03-29 13:17:19 +04:00
// only do the mangling for non-generic types (because we don't want to convert
// the double underscores in two adjacent _$$$_ or _$$$$_ markers)
if ( s . IndexOf ( "_$$$_" ) = = - 1 )
{
s = s . Replace ( "__" , "$$005F$$005F" ) ;
s = s . Replace ( "." , "__" ) ;
}
2006-07-26 11:57:18 +04:00
sb . Append ( 'L' ) . Append ( s ) ;
}
sep = "_$$_" ;
}
sb . Append ( "_$$$$_" ) ;
return sb . ToString ( ) ;
}
if ( AttributeHelper . IsNoPackagePrefix ( type )
& & name . IndexOf ( '$' ) = = - 1 )
2004-08-17 13:05:21 +04:00
{
2006-01-23 13:18:44 +03:00
return name . Replace ( '+' , '$' ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
2006-01-23 13:18:44 +03:00
return MangleTypeName ( name ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private static string MangleTypeName ( string name )
2004-08-17 13:05:21 +04:00
{
2005-06-22 17:02:03 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( NamePrefix , NamePrefix . Length + name . Length ) ;
2005-06-27 13:06:57 +04:00
bool escape = false ;
2008-04-21 12:19:20 +04:00
bool nested = false ;
2005-06-22 17:02:03 +04:00
for ( int i = 0 ; i < name . Length ; i + + )
{
char c = name [ i ] ;
2005-06-27 13:06:57 +04:00
if ( c = = '+' & & ! escape & & ( sb . Length = = 0 | | sb [ sb . Length - 1 ] ! = '$' ) )
2005-06-22 17:02:03 +04:00
{
2008-04-21 12:19:20 +04:00
nested = true ;
2005-06-22 17:02:03 +04:00
sb . Append ( '$' ) ;
}
2005-06-27 13:06:57 +04:00
else if ( "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" . IndexOf ( c ) ! = - 1
2008-04-21 12:19:20 +04:00
| | ( c = = '.' & & ! escape & & ! nested ) )
2005-06-22 17:02:03 +04:00
{
sb . Append ( c ) ;
}
else
{
2005-06-27 13:06:57 +04:00
sb . Append ( "$$" ) ;
2005-06-22 17:02:03 +04:00
sb . Append ( string . Format ( "{0:X4}" , ( int ) c ) ) ;
}
2005-06-27 13:06:57 +04:00
if ( c = = '\\' )
{
escape = ! escape ;
}
else
{
escape = false ;
}
2005-06-22 17:02:03 +04:00
}
return sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2005-06-22 17:02:03 +04:00
// NOTE if the name is not a valid mangled type name, no demangling is done and the
// original string is returned
2006-07-26 11:57:18 +04:00
// NOTE we don't enforce canonical form, this is not required, because we cannot
// guarantee it for unprefixed names anyway, so the caller is responsible for
// ensuring that the original name was in fact the canonical name.
2006-07-21 14:18:13 +04:00
internal static string DemangleTypeName ( string name )
2004-08-17 13:05:21 +04:00
{
2006-07-26 11:57:18 +04:00
if ( ! name . StartsWith ( NamePrefix ) )
2005-06-01 13:49:30 +04:00
{
2006-07-26 11:57:18 +04:00
return name . Replace ( '$' , '+' ) ;
2005-06-22 17:02:03 +04:00
}
2006-07-26 11:57:18 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( name . Length - NamePrefix . Length ) ;
for ( int i = NamePrefix . Length ; i < name . Length ; i + + )
2005-06-22 17:02:03 +04:00
{
char c = name [ i ] ;
if ( c = = '$' )
{
2006-07-26 11:57:18 +04:00
if ( i + 1 < name . Length & & name [ i + 1 ] ! = '$' )
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
sb . Append ( '+' ) ;
2005-06-22 17:02:03 +04:00
}
2005-06-27 13:06:57 +04:00
else
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
i + + ;
2006-07-26 11:57:18 +04:00
if ( i + 5 > name . Length )
2005-06-27 13:06:57 +04:00
{
return name ;
}
int digit0 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit1 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit2 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
int digit3 = "0123456789ABCDEF" . IndexOf ( name [ + + i ] ) ;
if ( digit0 = = - 1 | | digit1 = = - 1 | | digit2 = = - 1 | | digit3 = = - 1 )
{
return name ;
}
sb . Append ( ( char ) ( ( digit0 < < 12 ) + ( digit1 < < 8 ) + ( digit2 < < 4 ) + digit3 ) ) ;
2005-06-22 17:02:03 +04:00
}
}
else
{
sb . Append ( c ) ;
}
}
return sb . ToString ( ) ;
2004-08-17 13:05:21 +04:00
}
2006-05-15 13:08:01 +04:00
// TODO from a perf pov it may be better to allow creation of TypeWrappers,
// but to simply make sure they don't have ClassObject
internal static bool IsAllowedOutside ( Type type )
{
// SECURITY we never expose types from IKVM.Runtime, because doing so would lead to a security hole,
// since the reflection implementation lives inside this assembly, all internal members would
// be accessible through Java reflection.
2007-12-19 14:28:09 +03:00
#if ! FIRST_PASS & & ! STATIC_COMPILER
2006-05-15 13:08:01 +04:00
if ( type . Assembly = = typeof ( DotNetTypeWrapper ) . Assembly )
{
return false ;
}
2007-12-28 17:36:30 +03:00
if ( type . Assembly = = IKVM . NativeCode . java . lang . SecurityManager . jniAssembly )
2007-12-18 12:56:11 +03:00
{
return false ;
}
#endif
2007-11-26 12:01:35 +03:00
if ( type . ContainsGenericParameters )
2006-05-15 13:08:01 +04:00
{
return false ;
}
return true ;
}
private class DelegateInnerClassTypeWrapper : TypeWrapper
{
2008-03-03 10:05:19 +03:00
private readonly Type fakeType ;
2006-05-15 13:08:01 +04:00
2006-07-26 18:16:52 +04:00
internal DelegateInnerClassTypeWrapper ( string name , Type delegateType , ClassLoaderWrapper classLoader )
2006-05-15 13:08:01 +04:00
: base ( Modifiers . Public | Modifiers . Interface | Modifiers . Abstract , name , null )
{
2008-03-03 10:05:19 +03:00
#if STATIC_COMPILER
this . fakeType = FakeTypes . GetDelegateType ( delegateType ) ;
#elif ! FIRST_PASS
this . fakeType = typeof ( ikvm . @internal . DelegateInterface < > ) . MakeGenericType ( delegateType ) ;
#endif
2006-05-15 13:08:01 +04:00
MethodInfo invoke = delegateType . GetMethod ( "Invoke" ) ;
ParameterInfo [ ] parameters = invoke . GetParameters ( ) ;
2006-08-26 17:00:50 +04:00
TypeWrapper [ ] argTypeWrappers = new TypeWrapper [ parameters . Length ] ;
2006-05-15 13:08:01 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( "(" ) ;
2006-08-26 17:00:50 +04:00
for ( int i = 0 ; i < parameters . Length ; i + + )
2006-05-15 13:08:01 +04:00
{
2006-08-26 17:00:50 +04:00
argTypeWrappers [ i ] = ClassLoaderWrapper . GetWrapperFromType ( parameters [ i ] . ParameterType ) ;
2006-05-15 13:08:01 +04:00
sb . Append ( argTypeWrappers [ i ] . SigName ) ;
}
TypeWrapper returnType = ClassLoaderWrapper . GetWrapperFromType ( invoke . ReturnType ) ;
sb . Append ( ")" ) . Append ( returnType . SigName ) ;
2006-08-26 17:00:50 +04:00
MethodWrapper invokeMethod = new DynamicOnlyMethodWrapper ( this , "Invoke" , sb . ToString ( ) , returnType , argTypeWrappers ) ;
2006-05-15 13:08:01 +04:00
SetMethods ( new MethodWrapper [ ] { invokeMethod } ) ;
SetFields ( FieldWrapper . EmptyArray ) ;
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
2008-03-03 10:05:19 +03:00
return ClassLoaderWrapper . GetWrapperFromType ( fakeType . GetGenericArguments ( ) [ 0 ] ) ;
2006-05-15 13:08:01 +04:00
}
}
internal override void Finish ( )
{
}
internal override ClassLoaderWrapper GetClassLoader ( )
{
return DeclaringTypeWrapper . GetClassLoader ( ) ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericSignature ( )
{
return null ;
}
internal override TypeWrapper [ ] InnerClasses
{
get
{
return TypeWrapper . EmptyArray ;
}
}
internal override TypeWrapper [ ] Interfaces
{
get
{
return TypeWrapper . EmptyArray ;
}
}
internal override Type TypeAsTBD
{
get
{
2008-03-03 10:05:19 +03:00
return fakeType ;
2006-08-26 17:00:50 +04:00
}
}
}
2008-08-21 10:53:48 +04:00
private class DynamicOnlyMethodWrapper : MethodWrapper , ICustomInvoke
2006-08-26 17:00:50 +04:00
{
internal DynamicOnlyMethodWrapper ( TypeWrapper declaringType , string name , string sig , TypeWrapper returnType , TypeWrapper [ ] parameterTypes )
: base ( declaringType , name , sig , null , returnType , parameterTypes , Modifiers . Public | Modifiers . Abstract , MemberFlags . None )
{
}
2008-03-03 10:05:19 +03:00
internal override bool IsDynamicOnly
{
get
{
return true ;
}
}
2008-05-31 19:20:29 +04:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2008-08-25 08:16:59 +04:00
object ICustomInvoke . Invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
2008-05-31 19:20:29 +04:00
{
2008-08-21 10:53:48 +04:00
// a DynamicOnlyMethodWrapper is an interface method, but now that we've been called on an actual object instance,
// we can resolve to a real method and call that instead
TypeWrapper tw = TypeWrapper . FromClass ( NativeCode . ikvm . runtime . Util . getClassFromObject ( obj ) ) ;
MethodWrapper mw = tw . GetMethodWrapper ( this . Name , this . Signature , true ) ;
if ( mw = = null )
{
throw new java . lang . AbstractMethodError ( tw . Name + "." + this . Name + this . Signature ) ;
}
java . lang . reflect . Method m = ( java . lang . reflect . Method ) mw . ToMethodOrConstructor ( true ) ;
m . @override = true ;
return m . invoke ( obj , args , callerID ) ;
2008-05-31 19:20:29 +04:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-05-15 13:08:01 +04:00
}
2007-01-04 10:46:38 +03:00
private class EnumEnumTypeWrapper : TypeWrapper
{
2008-03-03 10:05:19 +03:00
private readonly Type fakeType ;
2007-01-04 10:46:38 +03:00
internal EnumEnumTypeWrapper ( string name , Type enumType )
: base ( Modifiers . Public | Modifiers . Enum | Modifiers . Final , name , ClassLoaderWrapper . LoadClassCritical ( "java.lang.Enum" ) )
{
2008-03-03 10:05:19 +03:00
#if STATIC_COMPILER
this . fakeType = FakeTypes . GetEnumType ( enumType ) ;
#elif ! FIRST_PASS
2008-04-22 10:50:22 +04:00
if ( enumType . Assembly . ReflectionOnly )
{
TypeWrapper decl = ClassLoaderWrapper . GetWrapperFromType ( enumType ) ;
TypeWrapperFactory factory = ClassLoaderWrapper . GetBootstrapClassLoader ( ) . GetTypeWrapperFactory ( ) ;
string basename = "<ReflectionOnlyType>" + enumType . FullName ;
name = basename ;
int index = 0 ;
while ( ! factory . ReserveName ( name ) )
{
name = basename + ( + + index ) ;
}
enumType = factory . ModuleBuilder . DefineEnum ( name , TypeAttributes . Public , typeof ( int ) ) . CreateType ( ) ;
ClassLoaderWrapper . SetWrapperForType ( enumType , decl ) ;
}
2008-03-03 10:05:19 +03:00
this . fakeType = typeof ( ikvm . @internal . EnumEnum < > ) . MakeGenericType ( enumType ) ;
#endif
2007-01-04 10:46:38 +03:00
}
2008-08-21 10:53:48 +04:00
internal object GetUnspecifiedValue ( )
{
return ( ( EnumFieldWrapper ) GetFieldWrapper ( "__unspecified" , this . SigName ) ) . GetValue ( ) ;
}
2007-01-04 10:46:38 +03:00
private class EnumFieldWrapper : FieldWrapper
{
private readonly int ordinal ;
private object val ;
internal EnumFieldWrapper ( TypeWrapper tw , string name , int ordinal )
: base ( tw , tw , name , tw . SigName , Modifiers . Public | Modifiers . Static | Modifiers . Final | Modifiers . Enum , null , MemberFlags . None )
{
this . ordinal = ordinal ;
}
2008-08-21 10:53:48 +04:00
internal object GetValue ( )
2007-01-04 10:46:38 +03:00
{
2008-03-03 10:05:19 +03:00
if ( val = = null )
2007-01-04 10:46:38 +03:00
{
2008-03-03 10:05:19 +03:00
System . Threading . Interlocked . CompareExchange ( ref val , Activator . CreateInstance ( this . DeclaringType . TypeAsTBD , BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . Instance , null , new object [ ] { this . Name , ordinal } , null ) , null ) ;
2007-01-04 10:46:38 +03:00
}
return val ;
}
2008-06-03 16:10:07 +04:00
protected override void EmitGetImpl ( CodeEmitter ilgen )
2007-01-04 10:46:38 +03:00
{
2008-03-03 10:05:19 +03:00
// TODO we should throw a NoSuchFieldError if at runtime we find out that the "field" doesn't exist
2008-04-22 10:48:30 +04:00
ilgen . Emit ( OpCodes . Ldtoken , this . DeclaringType . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . GetClassFromTypeHandle ) ;
2008-04-25 08:45:52 +04:00
ilgen . Emit ( OpCodes . Castclass , CoreClasses . java . lang . Class . Wrapper . TypeAsTBD ) ;
2007-01-04 10:46:38 +03:00
ilgen . Emit ( OpCodes . Ldstr , this . Name ) ;
this . DeclaringType . BaseTypeWrapper . GetMethodWrapper ( "valueOf" , "(Ljava.lang.Class;Ljava.lang.String;)Ljava.lang.Enum;" , false ) . EmitCall ( ilgen ) ;
2008-03-03 10:05:19 +03:00
ilgen . Emit ( OpCodes . Castclass , this . DeclaringType . TypeAsTBD ) ;
2007-01-04 10:46:38 +03:00
}
2008-06-03 16:10:07 +04:00
protected override void EmitSetImpl ( CodeEmitter ilgen )
2007-01-04 10:46:38 +03:00
{
}
}
2008-08-21 10:53:48 +04:00
private class EnumValuesMethodWrapper : MethodWrapper , ICustomInvoke
2007-01-04 15:54:10 +03:00
{
internal EnumValuesMethodWrapper ( TypeWrapper declaringType )
: base ( declaringType , "values" , "()[" + declaringType . SigName , null , declaringType . MakeArrayType ( 1 ) , TypeWrapper . EmptyArray , Modifiers . Public | Modifiers . Static , MemberFlags . None )
{
}
2008-03-03 10:05:19 +03:00
internal override bool IsDynamicOnly
{
get
{
return true ;
}
}
2008-05-31 19:20:29 +04:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2008-08-25 08:16:59 +04:00
object ICustomInvoke . Invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
2007-01-04 15:54:10 +03:00
{
FieldWrapper [ ] values = this . DeclaringType . GetFields ( ) ;
object [ ] array = ( object [ ] ) Array . CreateInstance ( this . DeclaringType . TypeAsArrayType , values . Length ) ;
for ( int i = 0 ; i < values . Length ; i + + )
{
2008-08-21 10:53:48 +04:00
array [ i ] = ( ( EnumFieldWrapper ) values [ i ] ) . GetValue ( ) ;
2007-01-04 15:54:10 +03:00
}
return array ;
}
2008-05-31 19:20:29 +04:00
#endif // !STATIC_COMPILER && !FIRST_PASS
2007-01-04 15:54:10 +03:00
}
2008-08-21 10:53:48 +04:00
private class EnumValueOfMethodWrapper : MethodWrapper , ICustomInvoke
2007-01-04 15:54:10 +03:00
{
internal EnumValueOfMethodWrapper ( TypeWrapper declaringType )
: base ( declaringType , "valueOf" , "(Ljava.lang.String;)" + declaringType . SigName , null , declaringType , new TypeWrapper [ ] { CoreClasses . java . lang . String . Wrapper } , Modifiers . Public | Modifiers . Static , MemberFlags . None )
{
}
2008-03-03 10:05:19 +03:00
internal override bool IsDynamicOnly
{
get
{
return true ;
}
}
2007-04-23 12:24:33 +04:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2008-08-25 08:16:59 +04:00
object ICustomInvoke . Invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
2007-01-04 15:54:10 +03:00
{
FieldWrapper [ ] values = this . DeclaringType . GetFields ( ) ;
for ( int i = 0 ; i < values . Length ; i + + )
{
if ( values [ i ] . Name . Equals ( args [ 0 ] ) )
{
2008-08-21 10:53:48 +04:00
return ( ( EnumFieldWrapper ) values [ i ] ) . GetValue ( ) ;
2007-01-04 15:54:10 +03:00
}
}
2007-04-23 12:24:33 +04:00
throw new java . lang . IllegalArgumentException ( "" + args [ 0 ] ) ;
2007-01-04 15:54:10 +03:00
}
2007-04-23 12:24:33 +04:00
#endif // !STATIC_COMPILER && !FIRST_PASS
2007-01-04 15:54:10 +03:00
}
2007-01-04 10:46:38 +03:00
protected override void LazyPublishMembers ( )
{
2008-08-15 16:01:06 +04:00
List < FieldWrapper > fields = new List < FieldWrapper > ( ) ;
2007-01-04 10:46:38 +03:00
int ordinal = 0 ;
2008-04-22 10:50:22 +04:00
foreach ( FieldInfo field in this . DeclaringTypeWrapper . TypeAsTBD . GetFields ( BindingFlags . Static | BindingFlags . Public ) )
2007-01-04 10:46:38 +03:00
{
if ( field . IsLiteral )
{
fields . Add ( new EnumFieldWrapper ( this , field . Name , ordinal + + ) ) ;
}
}
// TODO if the enum already has an __unspecified value, rename this one
fields . Add ( new EnumFieldWrapper ( this , "__unspecified" , ordinal + + ) ) ;
2008-08-15 16:01:06 +04:00
SetFields ( fields . ToArray ( ) ) ;
2007-01-04 15:54:10 +03:00
SetMethods ( new MethodWrapper [ ] { new EnumValuesMethodWrapper ( this ) , new EnumValueOfMethodWrapper ( this ) } ) ;
2007-01-04 10:46:38 +03:00
base . LazyPublishMembers ( ) ;
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
2008-03-03 10:05:19 +03:00
return ClassLoaderWrapper . GetWrapperFromType ( fakeType . GetGenericArguments ( ) [ 0 ] ) ;
2007-01-04 10:46:38 +03:00
}
}
internal override void Finish ( )
{
}
internal override ClassLoaderWrapper GetClassLoader ( )
{
return DeclaringTypeWrapper . GetClassLoader ( ) ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericSignature ( )
{
return null ;
}
internal override TypeWrapper [ ] InnerClasses
{
get
{
return TypeWrapper . EmptyArray ;
}
}
internal override TypeWrapper [ ] Interfaces
{
get
{
return TypeWrapper . EmptyArray ;
}
}
internal override Type TypeAsTBD
{
get
{
2008-03-03 10:05:19 +03:00
return fakeType ;
2007-01-04 10:46:38 +03:00
}
}
}
2007-04-15 12:01:19 +04:00
private abstract class AttributeAnnotationTypeWrapperBase : TypeWrapper
{
internal AttributeAnnotationTypeWrapperBase ( string name )
: base ( Modifiers . Public | Modifiers . Interface | Modifiers . Abstract | Modifiers . Annotation , name , null )
{
}
internal sealed override void Finish ( )
{
}
internal sealed override ClassLoaderWrapper GetClassLoader ( )
{
return DeclaringTypeWrapper . GetClassLoader ( ) ;
}
internal sealed override string [ ] GetEnclosingMethod ( )
{
return null ;
}
internal sealed override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal sealed override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal sealed override string GetGenericSignature ( )
{
return null ;
}
internal sealed override TypeWrapper [ ] Interfaces
{
get
{
return new TypeWrapper [ ] { ClassLoaderWrapper . GetBootstrapClassLoader ( ) . LoadClassByDottedName ( "java.lang.annotation.Annotation" ) } ;
}
}
}
private sealed class AttributeAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-06-15 16:29:11 +04:00
{
2008-03-03 10:05:19 +03:00
private readonly Type fakeType ;
private readonly Type attributeType ;
2007-04-15 12:01:19 +04:00
private TypeWrapper [ ] innerClasses ;
2006-06-15 16:29:11 +04:00
internal AttributeAnnotationTypeWrapper ( string name , Type attributeType )
2007-04-15 12:01:19 +04:00
: base ( name )
2006-06-15 16:29:11 +04:00
{
2008-03-03 10:05:19 +03:00
#if STATIC_COMPILER
this . fakeType = FakeTypes . GetAttributeType ( attributeType ) ;
#elif ! FIRST_PASS
this . fakeType = typeof ( ikvm . @internal . AttributeAnnotation < > ) . MakeGenericType ( attributeType ) ;
#endif
2006-06-15 16:29:11 +04:00
this . attributeType = attributeType ;
}
2007-04-12 13:27:17 +04:00
private static bool IsSupportedType ( Type type )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
// Java annotations only support one-dimensional arrays
if ( type . IsArray )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
type = type . GetElementType ( ) ;
}
return type = = typeof ( string )
| | type = = typeof ( bool )
| | type = = typeof ( byte )
| | type = = typeof ( char )
| | type = = typeof ( short )
| | type = = typeof ( int )
| | type = = typeof ( float )
| | type = = typeof ( long )
| | type = = typeof ( double )
| | type = = typeof ( Type )
| | type . IsEnum ;
}
internal static void GetConstructors ( Type type , out ConstructorInfo defCtor , out ConstructorInfo singleOneArgCtor )
{
defCtor = null ;
int oneArgCtorCount = 0 ;
ConstructorInfo oneArgCtor = null ;
foreach ( ConstructorInfo ci in type . GetConstructors ( BindingFlags . Public | BindingFlags . Instance ) )
{
ParameterInfo [ ] args = ci . GetParameters ( ) ;
if ( args . Length = = 0 )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
defCtor = ci ;
}
else if ( args . Length = = 1 )
{
2007-08-21 11:22:05 +04:00
// HACK special case for p/invoke StructLayout attribute
if ( type = = typeof ( System . Runtime . InteropServices . StructLayoutAttribute ) & & args [ 0 ] . ParameterType = = typeof ( short ) )
{
// we skip this constructor, so that the other one will be visible
continue ;
}
2007-04-12 13:27:17 +04:00
if ( IsSupportedType ( args [ 0 ] . ParameterType ) )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
oneArgCtor = ci ;
oneArgCtorCount + + ;
}
else
{
// set to two to make sure we don't see the oneArgCtor as viable
oneArgCtorCount = 2 ;
2006-06-15 16:29:11 +04:00
}
}
}
2007-04-12 13:27:17 +04:00
singleOneArgCtor = oneArgCtorCount = = 1 ? oneArgCtor : null ;
}
private class AttributeAnnotationMethodWrapper : DynamicOnlyMethodWrapper
{
private bool optional ;
internal AttributeAnnotationMethodWrapper ( AttributeAnnotationTypeWrapper tw , string name , Type type , bool optional )
: this ( tw , name , MapType ( type , false ) , optional )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
}
private static TypeWrapper MapType ( Type type , bool isArray )
{
if ( type = = typeof ( string ) )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
return CoreClasses . java . lang . String . Wrapper ;
}
else if ( type = = typeof ( bool ) )
{
return PrimitiveTypeWrapper . BOOLEAN ;
}
else if ( type = = typeof ( byte ) )
{
return PrimitiveTypeWrapper . BYTE ;
}
else if ( type = = typeof ( char ) )
{
return PrimitiveTypeWrapper . CHAR ;
}
else if ( type = = typeof ( short ) )
{
return PrimitiveTypeWrapper . SHORT ;
}
else if ( type = = typeof ( int ) )
{
return PrimitiveTypeWrapper . INT ;
}
else if ( type = = typeof ( float ) )
{
return PrimitiveTypeWrapper . FLOAT ;
}
else if ( type = = typeof ( long ) )
{
return PrimitiveTypeWrapper . LONG ;
}
else if ( type = = typeof ( double ) )
{
return PrimitiveTypeWrapper . DOUBLE ;
}
else if ( type = = typeof ( Type ) )
{
return CoreClasses . java . lang . Class . Wrapper ;
}
else if ( type . IsEnum )
{
foreach ( TypeWrapper tw in ClassLoaderWrapper . GetWrapperFromType ( type ) . InnerClasses )
2007-01-04 10:46:38 +03:00
{
2007-04-12 13:27:17 +04:00
if ( tw is EnumEnumTypeWrapper )
2007-01-04 10:46:38 +03:00
{
2007-04-12 13:27:17 +04:00
if ( ! isArray & & AttributeHelper . IsDefined ( type , typeof ( FlagsAttribute ) ) )
2007-01-04 10:46:38 +03:00
{
2007-04-12 13:27:17 +04:00
return tw . MakeArrayType ( 1 ) ;
2007-01-04 10:46:38 +03:00
}
2007-04-12 13:27:17 +04:00
return tw ;
2007-01-04 10:46:38 +03:00
}
}
2007-04-12 13:27:17 +04:00
throw new InvalidOperationException ( ) ;
}
else if ( ! isArray & & type . IsArray )
{
return MapType ( type . GetElementType ( ) , true ) . MakeArrayType ( 1 ) ;
}
else
{
throw new NotImplementedException ( ) ;
}
}
private AttributeAnnotationMethodWrapper ( AttributeAnnotationTypeWrapper tw , string name , TypeWrapper returnType , bool optional )
: base ( tw , name , "()" + returnType . SigName , returnType , TypeWrapper . EmptyArray )
{
this . optional = optional ;
}
internal bool IsOptional
{
get
{
return optional ;
2006-06-20 18:31:56 +04:00
}
}
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
protected override void LazyPublishMembers ( )
2006-06-20 18:31:56 +04:00
{
2008-08-15 16:01:06 +04:00
List < MethodWrapper > methods = new List < MethodWrapper > ( ) ;
2007-04-12 13:27:17 +04:00
ConstructorInfo defCtor ;
ConstructorInfo singleOneArgCtor ;
GetConstructors ( attributeType , out defCtor , out singleOneArgCtor ) ;
if ( singleOneArgCtor ! = null )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
methods . Add ( new AttributeAnnotationMethodWrapper ( this , "value" , singleOneArgCtor . GetParameters ( ) [ 0 ] . ParameterType , defCtor ! = null ) ) ;
2006-06-20 18:31:56 +04:00
}
2007-04-12 13:27:17 +04:00
foreach ( PropertyInfo pi in attributeType . GetProperties ( BindingFlags . Instance | BindingFlags . Public ) )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
if ( pi . CanRead & & pi . CanWrite & & IsSupportedType ( pi . PropertyType ) )
{
methods . Add ( new AttributeAnnotationMethodWrapper ( this , pi . Name , pi . PropertyType , true ) ) ;
}
2006-06-20 18:31:56 +04:00
}
2007-04-12 13:27:17 +04:00
foreach ( FieldInfo fi in attributeType . GetFields ( BindingFlags . Public | BindingFlags . Instance ) )
2007-01-04 10:46:38 +03:00
{
2007-04-12 13:27:17 +04:00
// TODO add other field validations to make sure it is appropriate
if ( ! fi . IsInitOnly & & IsSupportedType ( fi . FieldType ) )
{
methods . Add ( new AttributeAnnotationMethodWrapper ( this , fi . Name , fi . FieldType , true ) ) ;
}
}
2008-08-15 16:01:06 +04:00
SetMethods ( methods . ToArray ( ) ) ;
2007-04-12 13:27:17 +04:00
base . LazyPublishMembers ( ) ;
}
2007-04-23 12:24:33 +04:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2007-04-12 13:27:17 +04:00
internal override object GetAnnotationDefault ( MethodWrapper mw )
{
if ( ( ( AttributeAnnotationMethodWrapper ) mw ) . IsOptional )
{
if ( mw . ReturnType = = PrimitiveTypeWrapper . BOOLEAN )
{
2007-04-23 12:24:33 +04:00
return java . lang . Boolean . FALSE ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . BYTE )
{
2007-04-23 12:24:33 +04:00
return java . lang . Byte . valueOf ( ( byte ) 0 ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . CHAR )
{
2007-04-23 12:24:33 +04:00
return java . lang . Character . valueOf ( ( char ) 0 ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . SHORT )
{
2007-04-23 12:24:33 +04:00
return java . lang . Short . valueOf ( ( short ) 0 ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . INT )
{
2007-04-23 12:24:33 +04:00
return java . lang . Integer . valueOf ( 0 ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . FLOAT )
{
2007-04-23 12:24:33 +04:00
return java . lang . Float . valueOf ( 0F ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . LONG )
{
2007-04-23 12:24:33 +04:00
return java . lang . Long . valueOf ( 0L ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = PrimitiveTypeWrapper . DOUBLE )
{
2007-04-23 12:24:33 +04:00
return java . lang . Double . valueOf ( 0D ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType = = CoreClasses . java . lang . String . Wrapper )
{
return "" ;
}
else if ( mw . ReturnType = = CoreClasses . java . lang . Class . Wrapper )
{
2007-04-23 12:24:33 +04:00
return ( java . lang . Class ) typeof ( ikvm . @internal . __unspecified ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType is EnumEnumTypeWrapper )
{
2008-08-21 10:53:48 +04:00
EnumEnumTypeWrapper eetw = ( EnumEnumTypeWrapper ) mw . ReturnType ;
return eetw . GetUnspecifiedValue ( ) ;
2007-04-12 13:27:17 +04:00
}
else if ( mw . ReturnType . IsArray )
{
return Array . CreateInstance ( mw . ReturnType . TypeAsArrayType , 0 ) ;
}
2007-01-04 10:46:38 +03:00
}
2006-06-20 18:31:56 +04:00
return null ;
}
2007-04-23 12:24:33 +04:00
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-06-20 18:31:56 +04:00
2006-06-15 16:29:11 +04:00
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return ClassLoaderWrapper . GetWrapperFromType ( attributeType ) ;
}
}
2008-03-03 10:05:19 +03:00
internal override Type TypeAsTBD
{
get
{
return fakeType ;
}
}
2007-04-15 12:01:19 +04:00
private sealed class ReturnValueAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-06-15 16:29:11 +04:00
{
2008-03-03 10:05:19 +03:00
private readonly Type fakeType ;
private readonly AttributeAnnotationTypeWrapper declaringType ;
2006-06-15 16:29:11 +04:00
2007-04-15 12:01:19 +04:00
internal ReturnValueAnnotationTypeWrapper ( AttributeAnnotationTypeWrapper declaringType )
: base ( declaringType . Name + AttributeAnnotationReturnValueSuffix )
{
2008-03-03 10:05:19 +03:00
#if STATIC_COMPILER
this . fakeType = FakeTypes . GetAttributeReturnValueType ( declaringType . attributeType ) ;
#elif ! FIRST_PASS
this . fakeType = typeof ( ikvm . @internal . AttributeAnnotationReturnValue < > ) . MakeGenericType ( declaringType . attributeType ) ;
#endif
2007-04-15 12:01:19 +04:00
this . declaringType = declaringType ;
}
2006-06-15 16:29:11 +04:00
2007-04-15 12:01:19 +04:00
protected override void LazyPublishMembers ( )
{
TypeWrapper tw = declaringType ;
if ( declaringType . GetAttributeUsage ( ) . AllowMultiple )
{
tw = tw . MakeArrayType ( 1 ) ;
}
SetMethods ( new MethodWrapper [ ] { new DynamicOnlyMethodWrapper ( this , "value" , "()" + tw . SigName , tw , TypeWrapper . EmptyArray ) } ) ;
SetFields ( FieldWrapper . EmptyArray ) ;
}
2006-06-15 16:29:11 +04:00
2007-04-15 12:01:19 +04:00
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return declaringType ;
}
}
2006-06-15 16:29:11 +04:00
2007-04-15 12:01:19 +04:00
internal override TypeWrapper [ ] InnerClasses
{
get
{
return TypeWrapper . EmptyArray ;
}
}
2006-06-15 16:29:11 +04:00
2008-03-03 10:05:19 +03:00
internal override Type TypeAsTBD
{
get
{
return fakeType ;
}
}
2008-02-17 14:33:03 +03:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2007-04-15 12:01:19 +04:00
internal override object [ ] GetDeclaredAnnotations ( )
{
2008-02-17 14:33:03 +03:00
java . util . HashMap targetMap = new java . util . HashMap ( ) ;
2008-02-19 12:44:40 +03:00
targetMap . put ( "value" , new java . lang . annotation . ElementType [ ] { java . lang . annotation . ElementType . METHOD } ) ;
2008-02-17 14:33:03 +03:00
java . util . HashMap retentionMap = new java . util . HashMap ( ) ;
retentionMap . put ( "value" , java . lang . annotation . RetentionPolicy . RUNTIME ) ;
2007-04-15 12:01:19 +04:00
return new object [ ] {
2008-02-17 14:33:03 +03:00
java . lang . reflect . Proxy . newProxyInstance ( null , new java . lang . Class [ ] { typeof ( java . lang . annotation . Target ) } , new sun . reflect . annotation . AnnotationInvocationHandler ( typeof ( java . lang . annotation . Target ) , targetMap ) ) ,
java . lang . reflect . Proxy . newProxyInstance ( null , new java . lang . Class [ ] { typeof ( java . lang . annotation . Retention ) } , new sun . reflect . annotation . AnnotationInvocationHandler ( typeof ( java . lang . annotation . Retention ) , retentionMap ) )
} ;
2007-04-15 12:01:19 +04:00
}
#endif
2006-06-15 16:29:11 +04:00
2007-04-15 12:01:19 +04:00
#if ! COMPACT_FRAMEWORK
private class ReturnValueAnnotation : Annotation
2006-06-15 16:29:11 +04:00
{
2007-04-15 12:01:19 +04:00
private AttributeAnnotationTypeWrapper type ;
internal ReturnValueAnnotation ( AttributeAnnotationTypeWrapper type )
{
this . type = type ;
}
internal override void ApplyReturnValue ( ClassLoaderWrapper loader , MethodBuilder mb , ref ParameterBuilder pb , object annotation )
{
// TODO make sure the descriptor is correct
Annotation ann = type . Annotation ;
object [ ] arr = ( object [ ] ) annotation ;
for ( int i = 2 ; i < arr . Length ; i + = 2 )
{
if ( "value" . Equals ( arr [ i ] ) )
{
if ( pb = = null )
{
pb = mb . DefineParameter ( 0 , ParameterAttributes . None , null ) ;
}
object [ ] value = ( object [ ] ) arr [ i + 1 ] ;
if ( value [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ANNOTATION ) )
{
ann . Apply ( loader , pb , value ) ;
}
else
{
for ( int j = 1 ; j < value . Length ; j + + )
{
ann . Apply ( loader , pb , value [ j ] ) ;
}
}
break ;
}
}
}
internal override void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation )
{
}
internal override void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation )
{
}
internal override void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation )
{
}
internal override void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation )
{
}
internal override void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation )
{
}
internal override void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation )
{
}
2008-04-14 09:13:41 +04:00
internal override void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation )
{
}
2006-06-15 16:29:11 +04:00
}
2007-04-15 12:01:19 +04:00
internal override Annotation Annotation
2006-06-15 16:29:11 +04:00
{
2007-04-15 12:01:19 +04:00
get
{
return new ReturnValueAnnotation ( declaringType ) ;
}
2006-06-15 16:29:11 +04:00
}
2007-04-15 12:01:19 +04:00
#endif
2006-06-15 16:29:11 +04:00
}
2007-04-15 12:01:19 +04:00
private sealed class MultipleAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-08-26 17:00:50 +04:00
{
2008-03-03 10:05:19 +03:00
private readonly Type fakeType ;
private readonly AttributeAnnotationTypeWrapper declaringType ;
2007-04-15 12:01:19 +04:00
internal MultipleAnnotationTypeWrapper ( AttributeAnnotationTypeWrapper declaringType )
: base ( declaringType . Name + AttributeAnnotationMultipleSuffix )
2006-08-26 17:00:50 +04:00
{
2008-03-03 10:05:19 +03:00
#if STATIC_COMPILER
this . fakeType = FakeTypes . GetAttributeMultipleType ( declaringType . attributeType ) ;
#elif ! FIRST_PASS
this . fakeType = typeof ( ikvm . @internal . AttributeAnnotationMultiple < > ) . MakeGenericType ( declaringType . attributeType ) ;
#endif
2007-04-15 12:01:19 +04:00
this . declaringType = declaringType ;
2006-08-26 17:00:50 +04:00
}
2007-04-15 12:01:19 +04:00
protected override void LazyPublishMembers ( )
2006-06-15 16:29:11 +04:00
{
2007-04-15 12:01:19 +04:00
TypeWrapper tw = declaringType . MakeArrayType ( 1 ) ;
SetMethods ( new MethodWrapper [ ] { new DynamicOnlyMethodWrapper ( this , "value" , "()" + tw . SigName , tw , TypeWrapper . EmptyArray ) } ) ;
SetFields ( FieldWrapper . EmptyArray ) ;
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return declaringType ;
}
}
internal override TypeWrapper [ ] InnerClasses
{
get
{
return TypeWrapper . EmptyArray ;
}
}
2008-03-03 10:05:19 +03:00
internal override Type TypeAsTBD
{
get
{
return fakeType ;
}
}
2007-04-15 12:01:19 +04:00
#if ! STATIC_COMPILER
internal override object [ ] GetDeclaredAnnotations ( )
{
return declaringType . GetDeclaredAnnotations ( ) ;
}
#endif
#if ! COMPACT_FRAMEWORK
private class MultipleAnnotation : Annotation
{
private AttributeAnnotationTypeWrapper type ;
internal MultipleAnnotation ( AttributeAnnotationTypeWrapper type )
{
this . type = type ;
}
private static object [ ] UnwrapArray ( object annotation )
{
// TODO make sure the descriptor is correct
object [ ] arr = ( object [ ] ) annotation ;
for ( int i = 2 ; i < arr . Length ; i + = 2 )
{
if ( "value" . Equals ( arr [ i ] ) )
{
object [ ] value = ( object [ ] ) arr [ i + 1 ] ;
object [ ] rc = new object [ value . Length - 1 ] ;
Array . Copy ( value , 1 , rc , 0 , rc . Length ) ;
return rc ;
}
}
return new object [ 0 ] ;
}
internal override void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , mb , ann ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , ab , ann ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , cb , ann ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , fb , ann ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , pb , ann ) ;
}
}
internal override void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , tb , ann ) ;
}
}
2008-04-14 09:13:41 +04:00
internal override void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation )
{
Annotation annot = type . Annotation ;
foreach ( object ann in UnwrapArray ( annotation ) )
{
annot . Apply ( loader , pb , ann ) ;
}
}
2006-08-26 17:00:50 +04:00
}
2007-04-15 12:01:19 +04:00
internal override Annotation Annotation
{
get
{
return new MultipleAnnotation ( declaringType ) ;
}
}
#endif
2006-08-26 17:00:50 +04:00
}
2007-04-15 12:01:19 +04:00
internal override TypeWrapper [ ] InnerClasses
2006-08-26 17:00:50 +04:00
{
get
{
2007-04-15 12:01:19 +04:00
lock ( this )
{
if ( innerClasses = = null )
{
2008-08-15 16:01:06 +04:00
List < TypeWrapper > list = new List < TypeWrapper > ( ) ;
2007-04-15 12:01:19 +04:00
AttributeUsageAttribute attr = GetAttributeUsage ( ) ;
if ( ( attr . ValidOn & AttributeTargets . ReturnValue ) ! = 0 )
{
list . Add ( GetClassLoader ( ) . RegisterInitiatingLoader ( new ReturnValueAnnotationTypeWrapper ( this ) ) ) ;
}
if ( attr . AllowMultiple )
{
list . Add ( GetClassLoader ( ) . RegisterInitiatingLoader ( new MultipleAnnotationTypeWrapper ( this ) ) ) ;
}
2008-08-15 16:01:06 +04:00
innerClasses = list . ToArray ( ) ;
2007-04-15 12:01:19 +04:00
}
}
return innerClasses ;
2006-06-15 16:29:11 +04:00
}
}
2008-03-03 10:05:19 +03:00
internal override bool IsFakeTypeContainer
{
get
{
return true ;
}
}
2007-04-15 12:01:19 +04:00
private AttributeUsageAttribute GetAttributeUsage ( )
2007-01-04 10:46:38 +03:00
{
2007-04-15 12:01:19 +04:00
AttributeTargets validOn = AttributeTargets . All ;
bool allowMultiple = false ;
bool inherited = true ;
2007-03-13 10:44:23 +03:00
foreach ( CustomAttributeData cad in CustomAttributeData . GetCustomAttributes ( attributeType ) )
{
if ( cad . Constructor . DeclaringType = = typeof ( AttributeUsageAttribute ) )
{
if ( cad . ConstructorArguments . Count = = 1 & & cad . ConstructorArguments [ 0 ] . ArgumentType = = typeof ( AttributeTargets ) )
{
validOn = ( AttributeTargets ) cad . ConstructorArguments [ 0 ] . Value ;
2007-04-15 12:01:19 +04:00
}
foreach ( CustomAttributeNamedArgument cana in cad . NamedArguments )
{
if ( cana . MemberInfo . Name = = "AllowMultiple" )
{
allowMultiple = ( bool ) cana . TypedValue . Value ;
}
else if ( cana . MemberInfo . Name = = "Inherited" )
{
inherited = ( bool ) cana . TypedValue . Value ;
}
2007-03-13 10:44:23 +03:00
}
}
}
2007-04-15 12:01:19 +04:00
AttributeUsageAttribute attr = new AttributeUsageAttribute ( validOn ) ;
attr . AllowMultiple = allowMultiple ;
attr . Inherited = inherited ;
return attr ;
}
2008-02-17 14:33:03 +03:00
#if ! STATIC_COMPILER & & ! FIRST_PASS
2007-04-15 12:01:19 +04:00
internal override object [ ] GetDeclaredAnnotations ( )
{
// note that AttributeUsageAttribute.Inherited does not map to java.lang.annotation.Inherited
AttributeTargets validOn = GetAttributeUsage ( ) . ValidOn ;
2008-02-17 14:33:03 +03:00
List < java . lang . annotation . ElementType > targets = new List < java . lang . annotation . ElementType > ( ) ;
if ( ( validOn & ( AttributeTargets . Class | AttributeTargets . Struct | AttributeTargets . Enum | AttributeTargets . Delegate | AttributeTargets . Assembly ) ) ! = 0 )
2007-03-13 10:44:23 +03:00
{
2008-02-17 14:33:03 +03:00
targets . Add ( java . lang . annotation . ElementType . TYPE ) ;
2007-03-13 10:44:23 +03:00
}
2008-02-17 14:33:03 +03:00
if ( ( validOn & AttributeTargets . Constructor ) ! = 0 )
2007-03-13 10:44:23 +03:00
{
2008-02-17 14:33:03 +03:00
targets . Add ( java . lang . annotation . ElementType . CONSTRUCTOR ) ;
2007-03-13 10:44:23 +03:00
}
2008-02-17 14:33:03 +03:00
if ( ( validOn & AttributeTargets . Field ) ! = 0 )
2007-03-13 10:44:23 +03:00
{
2008-02-17 14:33:03 +03:00
targets . Add ( java . lang . annotation . ElementType . FIELD ) ;
2007-03-13 10:44:23 +03:00
}
2008-02-17 14:33:03 +03:00
if ( ( validOn & AttributeTargets . Method ) ! = 0 )
2007-03-13 10:44:23 +03:00
{
2008-02-17 14:33:03 +03:00
targets . Add ( java . lang . annotation . ElementType . METHOD ) ;
2007-03-13 10:44:23 +03:00
}
2008-02-17 14:33:03 +03:00
if ( ( validOn & AttributeTargets . Parameter ) ! = 0 )
2007-03-13 10:44:23 +03:00
{
2008-02-17 14:33:03 +03:00
targets . Add ( java . lang . annotation . ElementType . PARAMETER ) ;
2007-03-13 10:44:23 +03:00
}
2008-02-17 14:33:03 +03:00
java . util . HashMap targetMap = new java . util . HashMap ( ) ;
targetMap . put ( "value" , targets . ToArray ( ) ) ;
java . util . HashMap retentionMap = new java . util . HashMap ( ) ;
retentionMap . put ( "value" , java . lang . annotation . RetentionPolicy . RUNTIME ) ;
2007-01-04 10:46:38 +03:00
return new object [ ] {
2008-02-17 14:33:03 +03:00
java . lang . reflect . Proxy . newProxyInstance ( null , new java . lang . Class [ ] { typeof ( java . lang . annotation . Target ) } , new sun . reflect . annotation . AnnotationInvocationHandler ( typeof ( java . lang . annotation . Target ) , targetMap ) ) ,
java . lang . reflect . Proxy . newProxyInstance ( null , new java . lang . Class [ ] { typeof ( java . lang . annotation . Retention ) } , new sun . reflect . annotation . AnnotationInvocationHandler ( typeof ( java . lang . annotation . Retention ) , retentionMap ) )
} ;
2007-01-04 10:46:38 +03:00
}
#endif
2006-07-06 17:53:51 +04:00
#if ! COMPACT_FRAMEWORK
2006-06-15 16:29:11 +04:00
private class AttributeAnnotation : Annotation
{
private Type type ;
internal AttributeAnnotation ( Type type )
{
this . type = type ;
}
2007-04-12 13:27:17 +04:00
private static object ConvertValue ( ClassLoaderWrapper loader , Type targetType , object obj )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
if ( targetType . IsEnum )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
// TODO check the obj descriptor matches the type we expect
if ( ( ( object [ ] ) obj ) [ 0 ] . Equals ( AnnotationDefaultAttribute . TAG_ARRAY ) )
{
object [ ] arr = ( object [ ] ) obj ;
string s = "" ;
string sep = "" ;
for ( int i = 1 ; i < arr . Length ; i + + )
{
// TODO check the obj descriptor matches the type we expect
string val = ( ( object [ ] ) arr [ i ] ) [ 2 ] . ToString ( ) ;
if ( val ! = "__unspecified" )
{
s + = sep + val ;
sep = ", " ;
}
}
if ( s = = "" )
{
return Activator . CreateInstance ( targetType ) ;
}
return Enum . Parse ( targetType , s ) ;
}
else
{
string s = ( ( object [ ] ) obj ) [ 2 ] . ToString ( ) ;
if ( s = = "__unspecified" )
{
// TODO instead of this, we should probably return null and handle that
return Activator . CreateInstance ( targetType ) ;
}
return Enum . Parse ( targetType , s ) ;
}
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
else if ( targetType = = typeof ( Type ) )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
// TODO check the obj descriptor matches the type we expect
return loader . FieldTypeWrapperFromSig ( ( ( string ) ( ( object [ ] ) obj ) [ 1 ] ) . Replace ( '/' , '.' ) ) . TypeAsTBD ;
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
else if ( targetType . IsArray )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
// TODO check the obj descriptor matches the type we expect
object [ ] arr = ( object [ ] ) obj ;
Type elementType = targetType . GetElementType ( ) ;
Array targetArray = Array . CreateInstance ( elementType , arr . Length - 1 ) ;
for ( int i = 1 ; i < arr . Length ; i + + )
{
targetArray . SetValue ( ConvertValue ( loader , elementType , arr [ i ] ) , i - 1 ) ;
}
return targetArray ;
}
else
{
return obj ;
2006-06-20 18:31:56 +04:00
}
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
private CustomAttributeBuilder MakeCustomAttributeBuilder ( ClassLoaderWrapper loader , object annotation )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
object [ ] arr = ( object [ ] ) annotation ;
ConstructorInfo defCtor ;
ConstructorInfo singleOneArgCtor ;
object ctorArg = null ;
GetConstructors ( type , out defCtor , out singleOneArgCtor ) ;
2008-08-15 16:01:06 +04:00
List < PropertyInfo > properties = new List < PropertyInfo > ( ) ;
List < object > propertyValues = new List < object > ( ) ;
List < FieldInfo > fields = new List < FieldInfo > ( ) ;
List < object > fieldValues = new List < object > ( ) ;
2007-04-12 13:27:17 +04:00
for ( int i = 2 ; i < arr . Length ; i + = 2 )
{
string name = ( string ) arr [ i ] ;
if ( name = = "value" & & singleOneArgCtor ! = null )
{
ctorArg = ConvertValue ( loader , singleOneArgCtor . GetParameters ( ) [ 0 ] . ParameterType , arr [ i + 1 ] ) ;
}
else
{
PropertyInfo pi = type . GetProperty ( name , BindingFlags . Public | BindingFlags . Instance ) ;
if ( pi ! = null )
{
properties . Add ( pi ) ;
propertyValues . Add ( ConvertValue ( loader , pi . PropertyType , arr [ i + 1 ] ) ) ;
}
else
{
FieldInfo fi = type . GetField ( name , BindingFlags . Public | BindingFlags . Instance ) ;
if ( fi ! = null )
{
fields . Add ( fi ) ;
fieldValues . Add ( ConvertValue ( loader , fi . FieldType , arr [ i + 1 ] ) ) ;
}
}
}
}
2007-04-15 12:01:19 +04:00
if ( ctorArg = = null & & defCtor = = null )
{
// TODO required argument is missing
}
2007-04-12 13:27:17 +04:00
return new CustomAttributeBuilder ( ctorArg = = null ? defCtor : singleOneArgCtor ,
ctorArg = = null ? new object [ 0 ] : new object [ ] { ctorArg } ,
2008-08-15 16:01:06 +04:00
properties . ToArray ( ) ,
propertyValues . ToArray ( ) ,
fields . ToArray ( ) ,
fieldValues . ToArray ( ) ) ;
2007-04-12 13:27:17 +04:00
}
internal override void Apply ( ClassLoaderWrapper loader , TypeBuilder tb , object annotation )
{
2007-08-21 11:22:05 +04:00
if ( type = = typeof ( System . Runtime . InteropServices . StructLayoutAttribute ) & & tb . BaseType ! = typeof ( object ) )
{
// we have to handle this explicitly, because if we apply an illegal StructLayoutAttribute,
// TypeBuilder.CreateType() will later on throw an exception.
Tracer . Error ( Tracer . Runtime , "StructLayoutAttribute cannot be applied to {0}, because it does not directly extend cli.System.Object" , tb . FullName ) ;
return ;
}
2007-04-12 13:27:17 +04:00
tb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ConstructorBuilder cb , object annotation )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
cb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , MethodBuilder mb , object annotation )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
mb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , FieldBuilder fb , object annotation )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
fb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-15 16:29:11 +04:00
}
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , ParameterBuilder pb , object annotation )
2006-06-15 16:29:11 +04:00
{
2007-04-12 13:27:17 +04:00
pb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-15 16:29:11 +04:00
}
2006-06-20 18:31:56 +04:00
2007-04-12 13:27:17 +04:00
internal override void Apply ( ClassLoaderWrapper loader , AssemblyBuilder ab , object annotation )
2006-06-20 18:31:56 +04:00
{
2007-04-12 13:27:17 +04:00
ab . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
2006-06-20 18:31:56 +04:00
}
2008-04-14 09:13:41 +04:00
internal override void Apply ( ClassLoaderWrapper loader , PropertyBuilder pb , object annotation )
{
pb . SetCustomAttribute ( MakeCustomAttributeBuilder ( loader , annotation ) ) ;
}
2006-06-15 16:29:11 +04:00
}
internal override Annotation Annotation
{
get
{
return new AttributeAnnotation ( attributeType ) ;
}
}
2006-07-06 17:53:51 +04:00
#endif //!COMPACT_FRAMEWORK
2006-06-15 16:29:11 +04:00
}
2005-06-01 13:49:30 +04:00
internal static TypeWrapper GetWrapperFromDotNetType ( Type type )
2004-10-04 23:30:53 +04:00
{
2009-02-24 09:11:17 +03:00
TypeWrapper tw ;
lock ( types )
{
types . TryGetValue ( type , out tw ) ;
}
if ( tw = = null )
{
tw = ClassLoaderWrapper . GetAssemblyClassLoader ( type . Assembly ) . GetWrapperFromAssemblyType ( type ) ;
lock ( types )
{
types [ type ] = tw ;
}
}
return tw ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
private static TypeWrapper GetBaseTypeWrapper ( Type type )
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if ( type . IsInterface )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return null ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( ClassLoaderWrapper . IsRemappedType ( type ) )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// Remapped types extend their alter ego
// (e.g. cli.System.Object must appear to be derived from java.lang.Object)
// except when they're sealed, of course.
if ( type . IsSealed )
{
return CoreClasses . java . lang . Object . Wrapper ;
}
return ClassLoaderWrapper . GetWrapperFromType ( type ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if ( ClassLoaderWrapper . IsRemappedType ( type . BaseType ) )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return GetWrapperFromDotNetType ( type . BaseType ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper . GetWrapperFromType ( type . BaseType ) ;
2004-12-21 13:26:51 +03:00
}
2004-10-04 23:30:53 +04:00
}
2008-02-10 12:05:53 +03:00
internal DotNetTypeWrapper ( Type type , string name )
: base ( GetModifiers ( type ) , name , GetBaseTypeWrapper ( type ) )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type . IsByRef ) , type . FullName ) ;
Debug . Assert ( ! ( type . IsPointer ) , type . FullName ) ;
2007-01-16 13:14:47 +03:00
Debug . Assert ( ! ( type . Name . EndsWith ( "[]" ) ) , type . FullName ) ;
2005-06-01 13:49:30 +04:00
Debug . Assert ( ! ( type is TypeBuilder ) , type . FullName ) ;
2005-12-07 12:06:32 +03:00
Debug . Assert ( ! ( AttributeHelper . IsJavaModule ( type . Module ) ) ) ;
2005-06-01 13:49:30 +04:00
this . type = type ;
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader ( )
2004-06-25 13:38:07 +04:00
{
2007-11-26 12:01:35 +03:00
if ( type . IsGenericType )
2006-07-26 14:33:52 +04:00
{
return ClassLoaderWrapper . GetGenericClassLoader ( this ) ;
}
2006-05-15 13:08:01 +04:00
return ClassLoaderWrapper . GetAssemblyClassLoader ( type . Assembly ) ;
2004-06-25 13:38:07 +04:00
}
2009-03-06 08:33:08 +03:00
private sealed class MulticastDelegateCtorMethodWrapper : MethodWrapper
{
internal MulticastDelegateCtorMethodWrapper ( TypeWrapper declaringType )
: base ( declaringType , "<init>" , "()V" , null , PrimitiveTypeWrapper . VOID , TypeWrapper . EmptyArray , Modifiers . Protected , MemberFlags . None )
{
}
}
2005-06-01 13:49:30 +04:00
private class DelegateMethodWrapper : MethodWrapper
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
private ConstructorInfo delegateConstructor ;
2006-05-15 13:08:01 +04:00
private DelegateInnerClassTypeWrapper iface ;
2005-06-01 13:49:30 +04:00
2006-05-15 13:08:01 +04:00
internal DelegateMethodWrapper ( TypeWrapper declaringType , DelegateInnerClassTypeWrapper iface )
2005-06-01 13:49:30 +04:00
: base ( declaringType , "<init>" , "(" + iface . SigName + ")V" , null , PrimitiveTypeWrapper . VOID , new TypeWrapper [ ] { iface } , Modifiers . Public , MemberFlags . None )
2004-12-21 13:26:51 +03:00
{
2006-05-15 13:08:01 +04:00
this . delegateConstructor = declaringType . TypeAsTBD . GetConstructor ( new Type [ ] { typeof ( object ) , typeof ( IntPtr ) } ) ;
this . iface = iface ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitNewobj ( CodeEmitter ilgen , MethodAnalyzer ma , int opcodeIndex )
2004-12-21 13:26:51 +03:00
{
2006-08-26 17:00:50 +04:00
TypeWrapper targetType = ma = = null ? null : ma . GetStackTypeWrapper ( opcodeIndex , 0 ) ;
if ( targetType = = null | | targetType . IsInterface )
{
MethodInfo createDelegate = typeof ( Delegate ) . GetMethod ( "CreateDelegate" , new Type [ ] { typeof ( Type ) , typeof ( object ) , typeof ( string ) } ) ;
LocalBuilder targetObj = ilgen . DeclareLocal ( typeof ( object ) ) ;
ilgen . Emit ( OpCodes . Stloc , targetObj ) ;
ilgen . Emit ( OpCodes . Ldtoken , delegateConstructor . DeclaringType ) ;
ilgen . Emit ( OpCodes . Call , typeof ( Type ) . GetMethod ( "GetTypeFromHandle" , new Type [ ] { typeof ( RuntimeTypeHandle ) } ) ) ;
ilgen . Emit ( OpCodes . Ldloc , targetObj ) ;
ilgen . Emit ( OpCodes . Ldstr , "Invoke" ) ;
ilgen . Emit ( OpCodes . Call , createDelegate ) ;
ilgen . Emit ( OpCodes . Castclass , delegateConstructor . DeclaringType ) ;
}
else
{
ilgen . Emit ( OpCodes . Dup ) ;
// we know that a DelegateInnerClassTypeWrapper has only one method
Debug . Assert ( iface . GetMethods ( ) . Length = = 1 ) ;
MethodWrapper mw = targetType . GetMethodWrapper ( "Invoke" , iface . GetMethods ( ) [ 0 ] . Signature , true ) ;
// TODO linking here is not safe
mw . Link ( ) ;
ilgen . Emit ( OpCodes . Ldvirtftn , ( MethodInfo ) mw . GetMethod ( ) ) ;
ilgen . Emit ( OpCodes . Newobj , delegateConstructor ) ;
}
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
}
private class ByRefMethodWrapper : SmartMethodWrapper
{
2008-05-20 11:43:42 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private bool [ ] byrefs ;
2008-05-20 11:43:42 +04:00
#endif
2005-06-01 13:49:30 +04:00
private Type [ ] args ;
internal ByRefMethodWrapper ( Type [ ] args , bool [ ] byrefs , TypeWrapper declaringType , string name , string sig , MethodBase method , TypeWrapper returnType , TypeWrapper [ ] parameterTypes , Modifiers modifiers , bool hideFromReflection )
: base ( declaringType , name , sig , method , returnType , parameterTypes , modifiers , hideFromReflection ? MemberFlags . HideFromReflection : MemberFlags . None )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
this . args = args ;
2008-05-20 11:43:42 +04:00
#if ! STATIC_COMPILER
2005-06-01 13:49:30 +04:00
this . byrefs = byrefs ;
2008-05-20 11:43:42 +04:00
#endif
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
protected override void CallImpl ( CodeEmitter ilgen )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod ( ) ;
MethodInfo mi = mb as MethodInfo ;
if ( mi ! = null )
{
ilgen . Emit ( OpCodes . Call , mi ) ;
}
else
{
ilgen . Emit ( OpCodes . Call , ( ConstructorInfo ) mb ) ;
}
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
protected override void CallvirtImpl ( CodeEmitter ilgen )
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Callvirt , ( MethodInfo ) GetMethod ( ) ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
protected override void NewobjImpl ( CodeEmitter ilgen )
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen . Emit ( OpCodes . Newobj , ( ConstructorInfo ) GetMethod ( ) ) ;
2004-06-25 13:38:07 +04:00
}
2004-12-21 13:26:51 +03:00
2008-06-03 16:10:07 +04:00
protected override void PreEmit ( CodeEmitter ilgen )
2005-06-01 13:49:30 +04:00
{
LocalBuilder [ ] locals = new LocalBuilder [ args . Length ] ;
for ( int i = args . Length - 1 ; i > = 0 ; i - - )
{
Type type = args [ i ] ;
if ( type . IsByRef )
{
2006-07-05 12:46:56 +04:00
type = ArrayTypeWrapper . MakeArrayType ( type . GetElementType ( ) , 1 ) ;
2005-06-01 13:49:30 +04:00
}
locals [ i ] = ilgen . DeclareLocal ( type ) ;
ilgen . Emit ( OpCodes . Stloc , locals [ i ] ) ;
}
for ( int i = 0 ; i < args . Length ; i + + )
{
ilgen . Emit ( OpCodes . Ldloc , locals [ i ] ) ;
if ( args [ i ] . IsByRef )
{
ilgen . Emit ( OpCodes . Ldc_I4_0 ) ;
ilgen . Emit ( OpCodes . Ldelema , args [ i ] . GetElementType ( ) ) ;
}
}
base . PreEmit ( ilgen ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsVisible ( Type type )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
return type . IsPublic | | ( type . IsNestedPublic & & IsVisible ( type . DeclaringType ) ) ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
private class EnumWrapMethodWrapper : MethodWrapper
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
internal EnumWrapMethodWrapper ( DotNetTypeWrapper tw , TypeWrapper fieldType )
: base ( tw , "wrap" , "(" + fieldType . SigName + ")" + tw . SigName , null , tw , new TypeWrapper [ ] { fieldType } , Modifiers . Static | Modifiers . Public , MemberFlags . None )
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitCall ( CodeEmitter ilgen )
2005-06-01 13:49:30 +04:00
{
// We don't actually need to do anything here!
// The compiler will insert a boxing operation after calling us and that will
// result in our argument being boxed (since that's still sitting on the stack).
}
2005-12-07 12:06:32 +03:00
#endif
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal class EnumValueFieldWrapper : FieldWrapper
2003-08-21 14:06:34 +04:00
{
2006-11-27 10:39:30 +03:00
private Type underlyingType ;
2005-06-01 13:49:30 +04:00
internal EnumValueFieldWrapper ( DotNetTypeWrapper tw , TypeWrapper fieldType )
2006-04-05 12:18:58 +04:00
: base ( tw , fieldType , "Value" , fieldType . SigName , new ExModifiers ( Modifiers . Public | Modifiers . Final , false ) , null )
2004-12-21 13:26:51 +03:00
{
2006-11-27 10:39:30 +03:00
underlyingType = Enum . GetUnderlyingType ( tw . type ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
protected override void EmitGetImpl ( CodeEmitter ilgen )
2004-12-21 13:26:51 +03:00
{
2006-11-27 10:39:30 +03:00
// NOTE if the reference on the stack is null, we *want* the NullReferenceException, so we don't use TypeWrapper.EmitUnbox
ilgen . LazyEmitUnbox ( underlyingType ) ;
ilgen . LazyEmitLdobj ( underlyingType ) ;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2008-06-03 16:10:07 +04:00
protected override void EmitSetImpl ( CodeEmitter ilgen )
2004-12-21 13:26:51 +03:00
{
2008-08-21 10:40:22 +04:00
// NOTE even though the field is final, JNI reflection can still be used to set its value!
LocalBuilder temp = ilgen . AllocTempLocal ( underlyingType ) ;
ilgen . Emit ( OpCodes . Stloc , temp ) ;
ilgen . Emit ( OpCodes . Unbox , underlyingType ) ;
ilgen . Emit ( OpCodes . Ldloc , temp ) ;
ilgen . Emit ( OpCodes . Stobj , underlyingType ) ;
ilgen . ReleaseTempLocal ( temp ) ;
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
// this method takes a boxed Enum and returns its value as a boxed primitive
// of the subset of Java primitives (i.e. byte, short, int, long)
internal static object GetEnumPrimitiveValue ( object obj )
2003-08-21 14:06:34 +04:00
{
2007-03-13 10:44:23 +03:00
return GetEnumPrimitiveValue ( Enum . GetUnderlyingType ( obj . GetType ( ) ) , obj ) ;
}
// this method can be used to convert an enum value or its underlying value to a Java primitive
internal static object GetEnumPrimitiveValue ( Type underlyingType , object obj )
{
2005-06-01 13:49:30 +04:00
if ( underlyingType = = typeof ( sbyte ) | | underlyingType = = typeof ( byte ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked ( ( byte ) ( ( IConvertible ) obj ) . ToInt32 ( null ) ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if ( underlyingType = = typeof ( short ) | | underlyingType = = typeof ( ushort ) )
{
return unchecked ( ( short ) ( ( IConvertible ) obj ) . ToInt32 ( null ) ) ;
}
else if ( underlyingType = = typeof ( int ) )
{
return ( ( IConvertible ) obj ) . ToInt32 ( null ) ;
}
else if ( underlyingType = = typeof ( uint ) )
{
return unchecked ( ( int ) ( ( IConvertible ) obj ) . ToUInt32 ( null ) ) ;
}
else if ( underlyingType = = typeof ( long ) )
{
return ( ( IConvertible ) obj ) . ToInt64 ( null ) ;
}
else if ( underlyingType = = typeof ( ulong ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked ( ( long ) ( ( IConvertible ) obj ) . ToUInt64 ( null ) ) ;
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException ( ) ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
}
private class ValueTypeDefaultCtor : MethodWrapper
{
internal ValueTypeDefaultCtor ( DotNetTypeWrapper tw )
: base ( tw , "<init>" , "()V" , null , PrimitiveTypeWrapper . VOID , TypeWrapper . EmptyArray , Modifiers . Public , MemberFlags . None )
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitNewobj ( CodeEmitter ilgen , MethodAnalyzer ma , int opcodeIndex )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
LocalBuilder local = ilgen . DeclareLocal ( DeclaringType . TypeAsTBD ) ;
ilgen . Emit ( OpCodes . Ldloc , local ) ;
ilgen . Emit ( OpCodes . Box , DeclaringType . TypeAsTBD ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
2006-11-20 12:21:38 +03:00
private class FinalizeMethodWrapper : MethodWrapper
{
internal FinalizeMethodWrapper ( DotNetTypeWrapper tw )
2008-11-03 10:02:29 +03:00
: base ( tw , "finalize" , "()V" , null , PrimitiveTypeWrapper . VOID , TypeWrapper . EmptyArray , Modifiers . Protected | Modifiers . Final , MemberFlags . None )
2006-11-20 12:21:38 +03:00
{
}
2008-06-03 16:10:07 +04:00
internal override void EmitCall ( CodeEmitter ilgen )
2006-11-20 12:21:38 +03:00
{
ilgen . Emit ( OpCodes . Pop ) ;
}
2008-06-03 16:10:07 +04:00
internal override void EmitCallvirt ( CodeEmitter ilgen )
2006-11-20 12:21:38 +03:00
{
ilgen . Emit ( OpCodes . Pop ) ;
}
}
private class CloneMethodWrapper : MethodWrapper
{
internal CloneMethodWrapper ( DotNetTypeWrapper tw )
2008-11-03 10:02:29 +03:00
: base ( tw , "clone" , "()Ljava.lang.Object;" , null , CoreClasses . java . lang . Object . Wrapper , TypeWrapper . EmptyArray , Modifiers . Protected | Modifiers . Final , MemberFlags . None )
2006-11-20 12:21:38 +03:00
{
}
2008-06-03 16:10:07 +04:00
internal override void EmitCall ( CodeEmitter ilgen )
2006-11-20 12:21:38 +03:00
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , ClassLoaderWrapper . LoadClassCritical ( "java.lang.Cloneable" ) . TypeAsBaseType ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel label1 = ilgen . DefineLabel ( ) ;
2006-11-20 12:21:38 +03:00
ilgen . Emit ( OpCodes . Brtrue_S , label1 ) ;
2008-06-03 16:10:07 +04:00
CodeEmitterLabel label2 = ilgen . DefineLabel ( ) ;
2006-11-20 12:21:38 +03:00
ilgen . Emit ( OpCodes . Brfalse_S , label2 ) ;
EmitHelper . Throw ( ilgen , "java.lang.CloneNotSupportedException" ) ;
ilgen . MarkLabel ( label2 ) ;
EmitHelper . Throw ( ilgen , "java.lang.NullPointerException" ) ;
ilgen . MarkLabel ( label1 ) ;
ilgen . Emit ( OpCodes . Call , typeof ( object ) . GetMethod ( "MemberwiseClone" , BindingFlags . Instance | BindingFlags . NonPublic , null , Type . EmptyTypes , null ) ) ;
}
2008-06-03 16:10:07 +04:00
internal override void EmitCallvirt ( CodeEmitter ilgen )
2006-11-20 12:21:38 +03:00
{
EmitCall ( ilgen ) ;
}
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers ( )
{
// special support for enums
if ( type . IsEnum )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
Type underlyingType = Enum . GetUnderlyingType ( type ) ;
if ( underlyingType = = typeof ( sbyte ) )
{
underlyingType = typeof ( byte ) ;
}
else if ( underlyingType = = typeof ( ushort ) )
{
underlyingType = typeof ( short ) ;
}
else if ( underlyingType = = typeof ( uint ) )
{
underlyingType = typeof ( int ) ;
}
else if ( underlyingType = = typeof ( ulong ) )
{
underlyingType = typeof ( long ) ;
}
TypeWrapper fieldType = ClassLoaderWrapper . GetWrapperFromType ( underlyingType ) ;
FieldInfo [ ] fields = type . GetFields ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . Static ) ;
2008-08-15 16:01:06 +04:00
List < FieldWrapper > fieldsList = new List < FieldWrapper > ( ) ;
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < fields . Length ; i + + )
{
if ( fields [ i ] . FieldType = = type )
{
string name = fields [ i ] . Name ;
if ( name = = "Value" )
{
name = "_Value" ;
}
else if ( name . StartsWith ( "_" ) & & name . EndsWith ( "Value" ) )
{
name = "_" + name ;
}
2007-12-17 10:43:06 +03:00
object val = EnumValueFieldWrapper . GetEnumPrimitiveValue ( underlyingType , fields [ i ] . GetRawConstantValue ( ) ) ;
2006-10-10 20:24:48 +04:00
fieldsList . Add ( new ConstantFieldWrapper ( this , fieldType , name , fieldType . SigName , Modifiers . Public | Modifiers . Static | Modifiers . Final , fields [ i ] , val , MemberFlags . None ) ) ;
2005-06-01 13:49:30 +04:00
}
}
fieldsList . Add ( new EnumValueFieldWrapper ( this , fieldType ) ) ;
2008-08-15 16:01:06 +04:00
SetFields ( fieldsList . ToArray ( ) ) ;
2007-02-20 19:11:46 +03:00
SetMethods ( new MethodWrapper [ ] { new EnumWrapMethodWrapper ( this , fieldType ) } ) ;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-08-21 14:06:34 +04:00
{
2008-08-15 16:01:06 +04:00
List < FieldWrapper > fieldsList = new List < FieldWrapper > ( ) ;
2005-06-01 13:49:30 +04:00
FieldInfo [ ] fields = type . GetFields ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < fields . Length ; i + + )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO for remapped types, instance fields need to be converted to static getter/setter methods
if ( fields [ i ] . FieldType . IsPointer )
{
// skip, pointer fields are not supported
}
else
{
// TODO handle name/signature clash
2006-04-05 12:18:58 +04:00
fieldsList . Add ( CreateFieldWrapperDotNet ( AttributeHelper . GetModifiers ( fields [ i ] , true ) . Modifiers , fields [ i ] . Name , fields [ i ] . FieldType , fields [ i ] ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-11-17 15:01:50 +03:00
}
2008-08-15 16:01:06 +04:00
SetFields ( fieldsList . ToArray ( ) ) ;
2007-02-20 19:11:46 +03:00
2008-08-15 16:01:06 +04:00
Dictionary < string , MethodWrapper > methodsList = new Dictionary < string , MethodWrapper > ( ) ;
2005-06-01 13:49:30 +04:00
// special case for delegate constructors!
if ( IsDelegate ( type ) )
{
TypeWrapper iface = InnerClasses [ 0 ] ;
2007-02-20 19:11:46 +03:00
DelegateMethodWrapper mw = new DelegateMethodWrapper ( this , ( DelegateInnerClassTypeWrapper ) iface ) ;
methodsList . Add ( mw . Name + mw . Signature , mw ) ;
2005-06-01 13:49:30 +04:00
}
2009-03-06 08:33:08 +03:00
// add a protected default constructor to MulticastDelegate to make it easier to define a delegate in Java
if ( type = = typeof ( MulticastDelegate ) )
{
methodsList . Add ( "<init>()V" , new MulticastDelegateCtorMethodWrapper ( this ) ) ;
}
2005-06-01 13:49:30 +04:00
ConstructorInfo [ ] constructors = type . GetConstructors ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < constructors . Length ; i + + )
2003-11-17 15:01:50 +03:00
{
2005-01-03 11:26:21 +03:00
string name ;
string sig ;
2006-12-05 10:52:25 +03:00
TypeWrapper [ ] args ;
TypeWrapper ret ;
if ( MakeMethodDescriptor ( constructors [ i ] , out name , out sig , out args , out ret ) )
2005-06-01 13:49:30 +04:00
{
2007-02-20 19:11:46 +03:00
MethodWrapper mw = CreateMethodWrapper ( name , sig , args , ret , constructors [ i ] , false ) ;
string key = mw . Name + mw . Signature ;
if ( ! methodsList . ContainsKey ( key ) )
2005-06-01 13:49:30 +04:00
{
2007-02-20 19:11:46 +03:00
methodsList . Add ( key , mw ) ;
2005-06-01 13:49:30 +04:00
}
}
}
2007-02-20 19:11:46 +03:00
if ( type . IsValueType & & ! methodsList . ContainsKey ( "<init>()V" ) )
2005-06-01 13:49:30 +04:00
{
// Value types have an implicit default ctor
2007-02-20 19:11:46 +03:00
methodsList . Add ( "<init>()V" , new ValueTypeDefaultCtor ( this ) ) ;
2005-06-01 13:49:30 +04:00
}
MethodInfo [ ] methods = type . GetMethods ( BindingFlags . DeclaredOnly | BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static | BindingFlags . Instance ) ;
for ( int i = 0 ; i < methods . Length ; i + + )
{
if ( methods [ i ] . IsStatic & & type . IsInterface )
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
// skip, Java cannot deal with static methods on interfaces
}
else
{
string name ;
string sig ;
2006-12-05 10:52:25 +03:00
TypeWrapper [ ] args ;
TypeWrapper ret ;
if ( MakeMethodDescriptor ( methods [ i ] , out name , out sig , out args , out ret ) )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
if ( ! methods [ i ] . IsStatic & & ! methods [ i ] . IsPrivate & & BaseTypeWrapper ! = null )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod ! = null & & baseMethod . IsFinal & & ! baseMethod . IsStatic & & ! baseMethod . IsPrivate )
{
continue ;
}
2004-11-04 15:50:28 +03:00
}
2007-02-20 19:11:46 +03:00
MethodWrapper mw = CreateMethodWrapper ( name , sig , args , ret , methods [ i ] , false ) ;
string key = mw . Name + mw . Signature ;
2008-08-15 16:01:06 +04:00
MethodWrapper existing ;
methodsList . TryGetValue ( key , out existing ) ;
2007-02-20 19:11:46 +03:00
if ( existing = = null | | existing is ByRefMethodWrapper )
{
methodsList [ key ] = mw ;
}
2004-11-04 15:50:28 +03:00
}
2007-02-19 14:31:38 +03:00
else if ( methods [ i ] . IsAbstract )
{
this . HasUnsupportedAbstractMethods = true ;
}
2003-12-20 01:19:18 +03:00
}
}
2007-06-21 09:02:12 +04:00
// make sure that all the interface methods that we implement are available as public methods,
// otherwise javac won't like the class.
2005-06-01 13:49:30 +04:00
if ( ! type . IsInterface )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
Type [ ] interfaces = type . GetInterfaces ( ) ;
for ( int i = 0 ; i < interfaces . Length ; i + + )
2003-12-20 01:19:18 +03:00
{
2007-06-21 09:02:12 +04:00
// we only handle public (or nested public) types, because we're potentially adding a
// method that should be callable by anyone through the interface
if ( IsVisible ( interfaces [ i ] ) )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
InterfaceMapping map = type . GetInterfaceMap ( interfaces [ i ] ) ;
for ( int j = 0 ; j < map . InterfaceMethods . Length ; j + + )
2003-12-20 01:19:18 +03:00
{
2007-06-21 09:02:12 +04:00
if ( ( ! map . TargetMethods [ j ] . IsPublic | | map . TargetMethods [ j ] . Name ! = map . InterfaceMethods [ j ] . Name )
& & map . TargetMethods [ j ] . DeclaringType = = type )
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
string name ;
string sig ;
2006-12-05 10:52:25 +03:00
TypeWrapper [ ] args ;
TypeWrapper ret ;
if ( MakeMethodDescriptor ( map . InterfaceMethods [ j ] , out name , out sig , out args , out ret ) )
2004-11-04 15:50:28 +03:00
{
2007-06-21 09:02:12 +04:00
string key = name + sig ;
2008-08-15 16:01:06 +04:00
MethodWrapper existing ;
methodsList . TryGetValue ( key , out existing ) ;
2007-06-21 09:02:12 +04:00
if ( existing = = null & & BaseTypeWrapper ! = null )
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper . GetMethodWrapper ( name , sig , true ) ;
if ( baseMethod ! = null & & ! baseMethod . IsStatic & & baseMethod . IsPublic )
{
continue ;
}
2004-11-04 15:50:28 +03:00
}
2007-06-21 09:02:12 +04:00
if ( existing = = null | | existing is ByRefMethodWrapper | | existing . IsStatic | | ! existing . IsPublic )
2005-06-01 13:49:30 +04:00
{
2007-06-21 09:02:12 +04:00
// TODO if existing != null, we need to rename the existing method (but this is complicated because
// it also affects subclasses). This is especially required is the existing method is abstract,
// because otherwise we won't be able to create any subclasses in Java.
2007-02-20 19:11:46 +03:00
methodsList [ key ] = CreateMethodWrapper ( name , sig , args , ret , map . InterfaceMethods [ j ] , true ) ;
2005-06-01 13:49:30 +04:00
}
2005-02-02 18:11:26 +03:00
}
2003-12-20 01:19:18 +03:00
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
// for non-final remapped types, we need to add all the virtual methods in our alter ego (which
// appears as our base class) and make them final (to prevent Java code from overriding these
// methods, which don't really exist).
if ( ClassLoaderWrapper . IsRemappedType ( type ) & & ! type . IsSealed & & ! type . IsInterface )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
// Finish the type, to make sure the methods are populated
this . BaseTypeWrapper . Finish ( ) ;
TypeWrapper baseTypeWrapper = this . BaseTypeWrapper ;
while ( baseTypeWrapper ! = null )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
foreach ( MethodWrapper m in baseTypeWrapper . GetMethods ( ) )
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! m . IsStatic & & ! m . IsFinal & & ( m . IsPublic | | m . IsProtected ) & & m . Name ! = "<init>" )
2004-04-23 18:21:43 +04:00
{
2007-02-20 19:11:46 +03:00
string key = m . Name + m . Signature ;
if ( ! methodsList . ContainsKey ( key ) )
2005-06-01 13:49:30 +04:00
{
2006-11-20 12:21:38 +03:00
if ( m . IsProtected )
{
if ( m . Name = = "finalize" & & m . Signature = = "()V" )
{
2007-02-20 19:11:46 +03:00
methodsList . Add ( key , new FinalizeMethodWrapper ( this ) ) ;
2006-11-20 12:21:38 +03:00
}
else if ( m . Name = = "clone" & & m . Signature = = "()Ljava.lang.Object;" )
{
2007-02-20 19:11:46 +03:00
methodsList . Add ( key , new CloneMethodWrapper ( this ) ) ;
2006-11-20 12:21:38 +03:00
}
else
{
// there should be a special MethodWrapper for this method
throw new InvalidOperationException ( "Missing protected method support for " + baseTypeWrapper . Name + "::" + m . Name + m . Signature ) ;
}
}
else
{
2007-02-20 19:11:46 +03:00
methodsList . Add ( key , new BaseFinalMethodWrapper ( this , m ) ) ;
2006-11-20 12:21:38 +03:00
}
2005-06-01 13:49:30 +04:00
}
2004-04-23 18:21:43 +04:00
}
}
2005-06-01 13:49:30 +04:00
baseTypeWrapper = baseTypeWrapper . BaseTypeWrapper ;
}
}
2007-02-20 19:11:46 +03:00
MethodWrapper [ ] methodArray = new MethodWrapper [ methodsList . Count ] ;
methodsList . Values . CopyTo ( methodArray , 0 ) ;
SetMethods ( methodArray ) ;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private class BaseFinalMethodWrapper : MethodWrapper
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodWrapper m ;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal BaseFinalMethodWrapper ( DotNetTypeWrapper tw , MethodWrapper m )
: base ( tw , m . Name , m . Signature , m . GetMethod ( ) , m . ReturnType , m . GetParameters ( ) , m . Modifiers | Modifiers . Final , MemberFlags . None )
{
this . m = m ;
}
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitCall ( CodeEmitter ilgen )
2005-06-01 13:49:30 +04:00
{
// we direct EmitCall to EmitCallvirt, because we always want to end up at the instancehelper method
// (EmitCall would go to our alter ego .NET type and that wouldn't be legal)
m . EmitCallvirt ( ilgen ) ;
}
2004-08-17 13:05:21 +04:00
2008-06-03 16:10:07 +04:00
internal override void EmitCallvirt ( CodeEmitter ilgen )
2005-06-01 13:49:30 +04:00
{
m . EmitCallvirt ( ilgen ) ;
}
2005-12-07 12:06:32 +03:00
#endif
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
2007-02-19 14:31:38 +03:00
internal static bool IsUnsupportedAbstractMethod ( MethodBase mb )
{
if ( mb . IsAbstract )
{
MethodInfo mi = ( MethodInfo ) mb ;
2008-11-17 09:15:16 +03:00
if ( mi . ReturnType . IsByRef | | IsPointerType ( mi . ReturnType ) )
2007-02-19 14:31:38 +03:00
{
return true ;
}
foreach ( ParameterInfo p in mi . GetParameters ( ) )
{
2008-11-17 09:15:16 +03:00
if ( p . ParameterType . IsByRef | | IsPointerType ( p . ParameterType ) )
2007-02-19 14:31:38 +03:00
{
return true ;
}
}
}
return false ;
}
2008-11-17 09:15:16 +03:00
private static bool IsPointerType ( Type type )
{
while ( type . HasElementType )
{
if ( type . IsPointer )
{
return true ;
}
type = type . GetElementType ( ) ;
}
return false ;
}
2006-12-05 10:52:25 +03:00
private bool MakeMethodDescriptor ( MethodBase mb , out string name , out string sig , out TypeWrapper [ ] args , out TypeWrapper ret )
2003-08-21 14:06:34 +04:00
{
2007-11-26 12:01:35 +03:00
if ( mb . IsGenericMethodDefinition )
2003-08-21 14:06:34 +04:00
{
2005-01-03 11:26:21 +03:00
name = null ;
sig = null ;
2006-12-05 10:52:25 +03:00
args = null ;
ret = null ;
2005-01-03 11:26:21 +03:00
return false ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
sb . Append ( '(' ) ;
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
2006-12-05 10:52:25 +03:00
args = new TypeWrapper [ parameters . Length ] ;
2005-06-01 13:49:30 +04:00
for ( int i = 0 ; i < parameters . Length ; i + + )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type type = parameters [ i ] . ParameterType ;
2008-11-17 09:15:16 +03:00
if ( IsPointerType ( type ) )
2004-10-04 23:30:53 +04:00
{
2005-01-03 11:26:21 +03:00
name = null ;
sig = null ;
2006-12-05 10:52:25 +03:00
args = null ;
ret = null ;
2005-01-03 11:26:21 +03:00
return false ;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
if ( type . IsByRef )
2003-08-26 15:24:17 +04:00
{
2006-07-05 12:46:56 +04:00
type = ArrayTypeWrapper . MakeArrayType ( type . GetElementType ( ) , 1 ) ;
2005-06-01 13:49:30 +04:00
if ( mb . IsAbstract )
{
// Since we cannot override methods with byref arguments, we don't report abstract
// methods with byref args.
name = null ;
sig = null ;
2006-12-05 10:52:25 +03:00
args = null ;
ret = null ;
2005-06-01 13:49:30 +04:00
return false ;
}
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper tw = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
args [ i ] = tw ;
sb . Append ( tw . SigName ) ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sb . Append ( ')' ) ;
if ( mb is ConstructorInfo )
2003-08-21 14:06:34 +04:00
{
2006-12-05 10:52:25 +03:00
ret = PrimitiveTypeWrapper . VOID ;
2005-06-01 13:49:30 +04:00
if ( mb . IsStatic )
{
name = "<clinit>" ;
}
else
{
name = "<init>" ;
}
sb . Append ( ret . SigName ) ;
sig = sb . ToString ( ) ;
return true ;
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
Type type = ( ( MethodInfo ) mb ) . ReturnType ;
2009-02-04 09:51:40 +03:00
if ( IsPointerType ( type ) | | type . IsByRef )
2005-06-01 13:49:30 +04:00
{
name = null ;
sig = null ;
2006-12-05 10:52:25 +03:00
ret = null ;
2005-06-01 13:49:30 +04:00
return false ;
}
2006-12-05 10:52:25 +03:00
ret = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
2005-06-01 13:49:30 +04:00
sb . Append ( ret . SigName ) ;
name = mb . Name ;
sig = sb . ToString ( ) ;
return true ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if ( interfaces = = null )
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Type [ ] interfaceTypes = type . GetInterfaces ( ) ;
interfaces = new TypeWrapper [ interfaceTypes . Length ] ;
2006-08-29 10:28:34 +04:00
for ( int i = 0 ; i < interfaceTypes . Length ; i + + )
2004-12-02 11:43:05 +03:00
{
2005-06-01 13:49:30 +04:00
if ( interfaceTypes [ i ] . DeclaringType ! = null & &
2005-12-07 12:06:32 +03:00
AttributeHelper . IsHideFromJava ( interfaceTypes [ i ] ) & &
2005-06-01 13:49:30 +04:00
interfaceTypes [ i ] . Name = = "__Interface" )
{
// we have to return the declaring type for ghost interfaces
interfaces [ i ] = ClassLoaderWrapper . GetWrapperFromType ( interfaceTypes [ i ] . DeclaringType ) ;
}
else
{
interfaces [ i ] = ClassLoaderWrapper . GetWrapperFromType ( interfaceTypes [ i ] ) ;
}
2004-12-02 11:43:05 +03:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
return interfaces ;
2004-08-17 13:05:21 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2006-06-15 16:29:11 +04:00
private static bool IsAttribute ( Type type )
{
2006-06-20 18:31:56 +04:00
if ( ! type . IsAbstract & & type . IsSubclassOf ( typeof ( Attribute ) ) & & IsVisible ( type ) )
{
2007-04-12 13:27:17 +04:00
/ /
// Based on the number of constructors and their arguments, we distinguish several types
// of attributes:
// | def ctor | single 1-arg ctor
// -----------------------------------------------------------------
// complex only (i.e. Annotation{N}) | |
// all optional fields/properties | X |
// required "value" | | X
// optional "value" | X | X
// -----------------------------------------------------------------
//
// TODO currently we don't support "complex only" attributes.
/ /
ConstructorInfo defCtor ;
ConstructorInfo singleOneArgCtor ;
AttributeAnnotationTypeWrapper . GetConstructors ( type , out defCtor , out singleOneArgCtor ) ;
return defCtor ! = null | | singleOneArgCtor ! = null ;
2006-06-20 18:31:56 +04:00
}
return false ;
2006-06-15 16:29:11 +04:00
}
2005-06-01 13:49:30 +04:00
private static bool IsDelegate ( Type type )
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
// HACK non-public delegates do not get the special treatment (because they are likely to refer to
// non-public types in the arg list and they're not really useful anyway)
// NOTE we don't have to check in what assembly the type lives, because this is a DotNetTypeWrapper,
// we know that it is a different assembly.
if ( ! type . IsAbstract & & type . IsSubclassOf ( typeof ( MulticastDelegate ) ) & & IsVisible ( type ) )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo invoke = type . GetMethod ( "Invoke" ) ;
if ( invoke ! = null )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
foreach ( ParameterInfo p in invoke . GetParameters ( ) )
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO at the moment we don't support delegates with pointer or byref parameters
if ( p . ParameterType . IsPointer | | p . ParameterType . IsByRef )
{
return false ;
}
2005-02-11 17:46:58 +03:00
}
2005-06-01 13:49:30 +04:00
return true ;
2005-02-11 17:46:58 +03:00
}
}
2005-06-01 13:49:30 +04:00
return false ;
2004-09-05 13:37:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] InnerClasses
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( innerClasses = = null )
2003-08-21 14:06:34 +04:00
{
2006-06-15 16:29:11 +04:00
Type [ ] nestedTypes = type . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic ) ;
2008-08-15 16:01:06 +04:00
List < TypeWrapper > list = new List < TypeWrapper > ( nestedTypes . Length ) ;
2006-06-15 16:29:11 +04:00
for ( int i = 0 ; i < nestedTypes . Length ; i + + )
{
2007-11-26 12:01:35 +03:00
if ( ! nestedTypes [ i ] . IsGenericTypeDefinition )
2006-06-15 16:29:11 +04:00
{
list . Add ( ClassLoaderWrapper . GetWrapperFromType ( nestedTypes [ i ] ) ) ;
}
}
2005-06-01 13:49:30 +04:00
if ( IsDelegate ( type ) )
{
2006-07-26 18:16:52 +04:00
ClassLoaderWrapper classLoader = GetClassLoader ( ) ;
list . Add ( classLoader . RegisterInitiatingLoader ( new DelegateInnerClassTypeWrapper ( Name + DelegateInterfaceSuffix , type , classLoader ) ) ) ;
2005-06-01 13:49:30 +04:00
}
2006-06-15 16:29:11 +04:00
if ( IsAttribute ( type ) )
2004-09-05 13:37:58 +04:00
{
2006-07-26 13:03:44 +04:00
list . Add ( GetClassLoader ( ) . RegisterInitiatingLoader ( new AttributeAnnotationTypeWrapper ( Name + AttributeAnnotationSuffix , type ) ) ) ;
2007-01-04 10:46:38 +03:00
}
if ( type . IsEnum & & IsVisible ( type ) )
{
list . Add ( GetClassLoader ( ) . RegisterInitiatingLoader ( new EnumEnumTypeWrapper ( Name + EnumEnumSuffix , type ) ) ) ;
2004-09-05 13:37:58 +04:00
}
2008-08-15 16:01:06 +04:00
innerClasses = list . ToArray ( ) ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
return innerClasses ;
2003-08-21 14:06:34 +04:00
}
}
2008-03-03 10:05:19 +03:00
internal override bool IsFakeTypeContainer
{
get
{
return IsDelegate ( type ) | | IsAttribute ( type ) | | ( type . IsEnum & & IsVisible ( type ) ) ;
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( outerClass = = null )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type outer = type . DeclaringType ;
2007-12-27 18:41:43 +03:00
if ( outer ! = null & & ! type . IsGenericType )
2005-06-01 13:49:30 +04:00
{
outerClass = ClassLoaderWrapper . GetWrapperFromType ( outer ) ;
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
return outerClass ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( DeclaringTypeWrapper ! = null )
{
return Modifiers | Modifiers . Static ;
}
return Modifiers ;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapperDotNet ( Modifiers modifiers , string name , Type fieldType , FieldInfo field )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper type = ClassLoaderWrapper . GetWrapperFromType ( fieldType ) ;
if ( field . IsLiteral )
{
2006-10-10 20:24:48 +04:00
return new ConstantFieldWrapper ( this , type , name , type . SigName , modifiers , field , null , MemberFlags . None ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2006-04-05 12:18:58 +04:00
return FieldWrapper . Create ( this , type , field , name , type . SigName , new ExModifiers ( modifiers , false ) ) ;
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
2006-12-05 10:52:25 +03:00
private MethodWrapper CreateMethodWrapper ( string name , string sig , TypeWrapper [ ] argTypeWrappers , TypeWrapper retTypeWrapper , MethodBase mb , bool privateInterfaceImplHack )
2003-08-21 14:06:34 +04:00
{
2006-04-05 12:18:58 +04:00
ExModifiers exmods = AttributeHelper . GetModifiers ( mb , true ) ;
Modifiers mods = exmods . Modifiers ;
2005-06-01 13:49:30 +04:00
if ( name = = "Finalize" & & sig = = "()V" & & ! mb . IsStatic & &
TypeAsBaseType . IsSubclassOf ( CoreClasses . java . lang . Object . Wrapper . TypeAsBaseType ) )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO if the .NET also has a "finalize" method, we need to hide that one (or rename it, or whatever)
MethodWrapper mw = new SimpleCallMethodWrapper ( this , "finalize" , "()V" , ( MethodInfo ) mb , null , null , mods , MemberFlags . None , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
mw . SetDeclaredExceptions ( new string [ ] { "java.lang.Throwable" } ) ;
return mw ;
}
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
Type [ ] args = new Type [ parameters . Length ] ;
bool hasByRefArgs = false ;
bool [ ] byrefs = null ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
args [ i ] = parameters [ i ] . ParameterType ;
if ( parameters [ i ] . ParameterType . IsByRef )
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
if ( byrefs = = null )
{
byrefs = new bool [ args . Length ] ;
}
byrefs [ i ] = true ;
hasByRefArgs = true ;
2003-08-26 15:24:17 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if ( privateInterfaceImplHack )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
mods & = ~ Modifiers . Abstract ;
2004-08-17 13:05:21 +04:00
mods | = Modifiers . Final ;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if ( hasByRefArgs )
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( ! ( mb is ConstructorInfo ) & & ! mb . IsStatic )
{
mods | = Modifiers . Final ;
}
2006-12-05 10:52:25 +03:00
return new ByRefMethodWrapper ( args , byrefs , this , name , sig , mb , retTypeWrapper , argTypeWrappers , mods , false ) ;
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
else
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if ( mb is ConstructorInfo )
{
2006-12-05 10:52:25 +03:00
return new SmartConstructorMethodWrapper ( this , name , sig , ( ConstructorInfo ) mb , argTypeWrappers , mods , MemberFlags . None ) ;
2005-06-01 13:49:30 +04:00
}
else
{
2006-12-05 10:52:25 +03:00
return new SmartCallMethodWrapper ( this , name , sig , ( MethodInfo ) mb , retTypeWrapper , argTypeWrappers , mods , MemberFlags . None , SimpleOpCode . Call , SimpleOpCode . Callvirt ) ;
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type ;
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return ClassLoaderWrapper . IsRemappedType ( type ) ;
}
2004-04-23 18:21:43 +04:00
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if ! COMPACT_FRAMEWORK
2008-06-03 16:10:07 +04:00
internal override void EmitInstanceOf ( TypeWrapper context , CodeEmitter ilgen )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsRemapped )
2004-10-19 17:43:55 +04:00
{
2006-05-23 16:49:16 +04:00
TypeWrapper shadow = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
2005-06-01 13:49:30 +04:00
MethodInfo method = shadow . TypeAsBaseType . GetMethod ( "__<instanceof>" ) ;
if ( method ! = null )
{
ilgen . Emit ( OpCodes . Call , method ) ;
return ;
}
2004-10-19 17:43:55 +04:00
}
2006-11-27 10:39:30 +03:00
ilgen . LazyEmit_instanceof ( type ) ;
2004-10-19 17:43:55 +04:00
}
2008-06-03 16:10:07 +04:00
internal override void EmitCheckcast ( TypeWrapper context , CodeEmitter ilgen )
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if ( IsRemapped )
2004-10-19 17:43:55 +04:00
{
2006-05-23 16:49:16 +04:00
TypeWrapper shadow = ClassLoaderWrapper . GetWrapperFromType ( type ) ;
2005-06-01 13:49:30 +04:00
MethodInfo method = shadow . TypeAsBaseType . GetMethod ( "__<checkcast>" ) ;
if ( method ! = null )
{
ilgen . Emit ( OpCodes . Call , method ) ;
return ;
}
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
EmitHelper . Castclass ( ilgen , type ) ;
2004-10-19 17:43:55 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-01-03 11:26:21 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2005-01-03 11:26:21 +03:00
{
2006-03-01 15:26:25 +03:00
if ( BaseTypeWrapper ! = null )
{
BaseTypeWrapper . Finish ( ) ;
}
foreach ( TypeWrapper tw in this . Interfaces )
{
tw . Finish ( ) ;
}
2005-01-03 11:26:21 +03:00
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2005-11-01 17:01:42 +03:00
internal override object [ ] GetDeclaredAnnotations ( )
{
2007-03-13 10:44:23 +03:00
if ( type . Assembly . ReflectionOnly )
{
2007-11-26 11:38:38 +03:00
// TODO on Whidbey this must be implemented
2007-03-13 10:44:23 +03:00
return null ;
}
2005-11-01 17:01:42 +03:00
return type . GetCustomAttributes ( false ) ;
}
2007-03-13 10:44:23 +03:00
internal override object [ ] GetFieldAnnotations ( FieldWrapper fw )
{
2008-02-29 10:08:04 +03:00
FieldInfo fi = fw . GetField ( ) ;
if ( fi = = null )
{
return null ;
}
if ( fi . DeclaringType . Assembly . ReflectionOnly )
{
// TODO on Whidbey this must be implemented
return null ;
}
return fi . GetCustomAttributes ( false ) ;
2007-03-13 10:44:23 +03:00
}
internal override object [ ] GetMethodAnnotations ( MethodWrapper mw )
{
2008-02-29 10:08:04 +03:00
MethodBase mb = mw . GetMethod ( ) ;
if ( mb = = null )
{
return null ;
}
if ( mb . DeclaringType . Assembly . ReflectionOnly )
{
// TODO on Whidbey this must be implemented
return null ;
}
return mb . GetCustomAttributes ( false ) ;
2007-03-13 10:44:23 +03:00
}
internal override object [ ] [ ] GetParameterAnnotations ( MethodWrapper mw )
{
2008-02-29 10:08:04 +03:00
MethodBase mb = mw . GetMethod ( ) ;
if ( mb = = null )
{
return null ;
}
if ( mb . DeclaringType . Assembly . ReflectionOnly )
{
// TODO on Whidbey this must be implemented
return null ;
}
ParameterInfo [ ] parameters = mb . GetParameters ( ) ;
object [ ] [ ] attribs = new object [ parameters . Length ] [ ] ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
attribs [ i ] = parameters [ i ] . GetCustomAttributes ( false ) ;
}
return attribs ;
2007-03-13 10:44:23 +03:00
}
2005-01-03 11:26:21 +03:00
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
sealed class ArrayTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private static TypeWrapper [ ] interfaces ;
private static MethodInfo clone ;
2006-07-27 18:44:51 +04:00
private readonly TypeWrapper ultimateElementTypeWrapper ;
private Type arrayType ;
2007-08-08 16:50:48 +04:00
private bool finished ;
2005-01-03 11:26:21 +03:00
2006-07-27 18:44:51 +04:00
internal ArrayTypeWrapper ( TypeWrapper ultimateElementTypeWrapper , string name )
: base ( Modifiers . Final | Modifiers . Abstract | ( ultimateElementTypeWrapper . Modifiers & Modifiers . Public ) , name , CoreClasses . java . lang . Object . Wrapper )
2003-08-21 14:06:34 +04:00
{
2006-07-27 18:44:51 +04:00
this . ultimateElementTypeWrapper = ultimateElementTypeWrapper ;
2006-10-12 10:44:16 +04:00
this . IsInternal = ultimateElementTypeWrapper . IsInternal ;
2006-03-23 14:57:41 +03:00
}
internal override ClassLoaderWrapper GetClassLoader ( )
{
2006-07-27 18:44:51 +04:00
return ultimateElementTypeWrapper . GetClassLoader ( ) ;
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
2005-08-05 12:40:54 +04:00
internal static MethodInfo CloneMethod
2004-12-22 11:04:10 +03:00
{
2005-08-05 12:40:54 +04:00
get
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if ( clone = = null )
{
clone = typeof ( Array ) . GetMethod ( "Clone" , BindingFlags . Public | BindingFlags . Instance , null , Type . EmptyTypes , null ) ;
}
return clone ;
2005-06-01 13:49:30 +04:00
}
2005-08-05 12:40:54 +04:00
}
protected override void LazyPublishMembers ( )
{
MethodWrapper mw = new SimpleCallMethodWrapper ( this , "clone" , "()Ljava.lang.Object;" , CloneMethod , CoreClasses . java . lang . Object . Wrapper , TypeWrapper . EmptyArray , Modifiers . Public , MemberFlags . HideFromReflection , SimpleOpCode . Callvirt , SimpleOpCode . Callvirt ) ;
2005-06-01 13:49:30 +04:00
mw . Link ( ) ;
SetMethods ( new MethodWrapper [ ] { mw } ) ;
SetFields ( FieldWrapper . EmptyArray ) ;
2004-12-22 11:04:10 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-07-27 18:44:51 +04:00
return Modifiers . Final | Modifiers . Abstract | ( ultimateElementTypeWrapper . ReflectiveModifiers & Modifiers . AccessMask ) ;
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
// for arrays the signature name is the same as the normal name
return Name ;
2003-02-22 15:28:12 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper [ ] Interfaces
{
get
{
if ( interfaces = = null )
{
TypeWrapper [ ] tw = new TypeWrapper [ 2 ] ;
tw [ 0 ] = ClassLoaderWrapper . LoadClassCritical ( "java.lang.Cloneable" ) ;
tw [ 1 ] = ClassLoaderWrapper . LoadClassCritical ( "java.io.Serializable" ) ;
interfaces = tw ;
}
return interfaces ;
}
}
internal override TypeWrapper [ ] InnerClasses
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper . EmptyArray ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null ;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-07-27 18:44:51 +04:00
if ( arrayType = = null )
{
arrayType = MakeArrayType ( ultimateElementTypeWrapper . TypeAsArrayType , this . ArrayRank ) ;
}
return arrayType ;
2005-06-01 13:49:30 +04:00
}
2003-02-22 15:28:12 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish ( )
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
lock ( this )
2003-02-22 15:28:12 +03:00
{
2007-08-08 16:50:48 +04:00
if ( ! finished )
2005-06-01 13:49:30 +04:00
{
2007-08-08 16:50:48 +04:00
finished = true ;
2006-07-27 18:44:51 +04:00
ultimateElementTypeWrapper . Finish ( ) ;
arrayType = MakeArrayType ( ultimateElementTypeWrapper . TypeAsArrayType , this . ArrayRank ) ;
2007-08-08 16:50:48 +04:00
ClassLoaderWrapper . ResetWrapperForType ( arrayType , this ) ;
2005-06-01 13:49:30 +04:00
}
2003-02-22 15:28:12 +03:00
}
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature ( )
{
return null ;
}
internal override string GetGenericMethodSignature ( MethodWrapper mw )
{
return null ;
}
internal override string GetGenericFieldSignature ( FieldWrapper fw )
{
return null ;
}
internal override string [ ] GetEnclosingMethod ( )
{
return null ;
}
2006-07-05 12:46:56 +04:00
internal static Type MakeArrayType ( Type type , int dims )
{
// NOTE this is not just an optimization, but it is also required to
// make sure that ReflectionOnly types stay ReflectionOnly types
// (in particular instantiations of generic types from mscorlib that
// have ReflectionOnly type parameters).
for ( int i = 0 ; i < dims ; i + + )
{
type = type . MakeArrayType ( ) ;
}
return type ;
}
2003-02-22 15:28:12 +03:00
}
}