25using System.Collections.Generic;
29#if IMPORTER || EXPORTER
36using System.Reflection;
37using System.Reflection.Emit;
51 sealed partial class RuntimeManagedJavaType
54 sealed partial class AttributeAnnotationJavaType : AttributeAnnotationJavaTypeBase
57 readonly
Type fakeType;
58 readonly
Type attributeType;
59 volatile RuntimeJavaType[] innerClasses;
66 internal AttributeAnnotationJavaType(RuntimeContext context,
string name,
Type attributeType) :
69#if IMPORTER || EXPORTER
70 this.fakeType = context.FakeTypes.GetAttributeType(attributeType);
72 this.fakeType = typeof(ikvm.@
internal.AttributeAnnotation<>).MakeGenericType(attributeType);
74 this.attributeType = attributeType;
77 static bool IsSupportedType(RuntimeContext context,
Type type)
80 if (ReflectUtil.IsVector(type))
81 type = type.GetElementType();
83 return type == context.Types.String
84 || type == context.Types.Boolean
85 || type == context.Types.Byte
86 || type == context.Types.Char
87 || type == context.Types.Int16
88 || type == context.Types.Int32
89 || type == context.Types.Single
90 || type == context.Types.Int64
91 || type == context.Types.Double
92 || type == context.Types.Type
99 int oneArgCtorCount = 0;
101 ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
105 if (constructors.Length == 2 && type.Assembly == context.Types.Object.Assembly)
109 if (p0.Length == 1 && p1.Length == 1)
111 Type t0 = p0[0].ParameterType;
112 Type t1 = p1[0].ParameterType;
113 bool swapped =
false;
121 if (t0.IsEnum && (t1 == context.Types.Byte || t1 == context.Types.Int16 || t1 == context.Types.Int32))
125 singleOneArgCtor = constructors[1];
129 singleOneArgCtor = constructors[0];
136 if (type.Assembly == context.Types.Object.Assembly)
138 if (type.FullName ==
"System.Runtime.CompilerServices.MethodImplAttribute")
143 if (p.Length == 1 && p[0].ParameterType.IsEnum)
145 singleOneArgCtor = ci;
155 if (args.Length == 0)
159 else if (args.Length == 1)
161 if (IsSupportedType(context, args[0].ParameterType))
173 singleOneArgCtor = oneArgCtorCount == 1 ? oneArgCtor :
null;
176 sealed class AttributeAnnotationJavaMethod : DynamicOnlyJavaMethod
179 readonly
bool optional;
188 internal AttributeAnnotationJavaMethod(AttributeAnnotationJavaType tw,
string name,
Type type,
bool optional) :
189 this(tw, name, MapType(tw.Context, type, false), optional)
194 static RuntimeJavaType MapType(RuntimeContext context,
Type type,
bool isArray)
196 if (type == context.Types.String)
198 return context.JavaBase.TypeOfJavaLangString;
200 else if (type == context.Types.Boolean)
202 return context.PrimitiveJavaTypeFactory.BOOLEAN;
204 else if (type == context.Types.Byte)
206 return context.PrimitiveJavaTypeFactory.BYTE;
208 else if (type == context.Types.Char)
210 return context.PrimitiveJavaTypeFactory.CHAR;
212 else if (type == context.Types.Int16)
214 return context.PrimitiveJavaTypeFactory.SHORT;
216 else if (type == context.Types.Int32)
218 return context.PrimitiveJavaTypeFactory.INT;
220 else if (type == context.Types.Single)
222 return context.PrimitiveJavaTypeFactory.FLOAT;
224 else if (type == context.Types.Int64)
226 return context.PrimitiveJavaTypeFactory.LONG;
228 else if (type == context.Types.Double)
230 return context.PrimitiveJavaTypeFactory.DOUBLE;
232 else if (type == context.Types.Type)
234 return context.JavaBase.TypeOfJavaLangClass;
236 else if (type.IsEnum)
238 foreach (RuntimeJavaType tw
in context.ClassLoaderFactory.GetJavaTypeFromType(type).InnerClasses)
240 if (tw is EnumEnumJavaType)
242 if (!isArray && type.IsDefined(context.Resolver.ResolveCoreType(typeof(FlagsAttribute).FullName).AsReflection(),
false))
244 return tw.MakeArrayType(1);
249 throw new InvalidOperationException();
251 else if (!isArray && ReflectUtil.IsVector(type))
253 return MapType(context, type.GetElementType(),
true).MakeArrayType(1);
257 throw new NotImplementedException();
268 private AttributeAnnotationJavaMethod(AttributeAnnotationJavaType tw,
string name, RuntimeJavaType returnType,
bool optional) :
269 base(tw, name,
"()" + returnType.SigName, returnType, Array.Empty<RuntimeJavaType>(),
MemberFlags.
None)
271 this.optional = optional;
274 internal override bool IsOptionalAttributeAnnotationValue
276 get {
return optional; }
280 protected override void LazyPublishMembers()
282 var methods =
new List<RuntimeJavaMethod>();
283 GetConstructors(Context, attributeType, out var defCtor, out var singleOneArgCtor);
285 if (singleOneArgCtor !=
null)
286 methods.Add(
new AttributeAnnotationJavaMethod(
this,
"value", singleOneArgCtor.GetParameters()[0].ParameterType, defCtor !=
null));
288 foreach (var pi
in attributeType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
294 var getter = pi.GetGetMethod();
295 var setter = pi.GetSetMethod();
297 if (getter !=
null && getter.GetParameters().Length == 0 && getter.ReturnType == pi.PropertyType && setter !=
null && (parameters = setter.GetParameters()).Length == 1 && parameters[0].ParameterType == pi.PropertyType && setter.ReturnType == Context.
Types.
Void && IsSupportedType(Context, pi.PropertyType))
298 AddMethodIfUnique(methods,
new AttributeAnnotationJavaMethod(
this, pi.Name, pi.PropertyType,
true));
301 foreach (var fi
in attributeType.GetFields(BindingFlags.Public | BindingFlags.Instance))
302 if (!fi.IsInitOnly && IsSupportedType(Context, fi.FieldType))
303 AddMethodIfUnique(methods,
new AttributeAnnotationJavaMethod(
this, fi.Name, fi.FieldType,
true));
305 SetMethods(methods.ToArray());
307 base.LazyPublishMembers();
310 static void AddMethodIfUnique(List<RuntimeJavaMethod> methods, RuntimeJavaMethod method)
312 foreach (var mw
in methods)
314 if (mw.Name == method.Name && mw.Signature == method.Signature)
324#if !IMPORTER && !FIRST_PASS && !EXPORTER
326 internal override object GetAnnotationDefault(RuntimeJavaMethod mw)
328 if (mw.IsOptionalAttributeAnnotationValue)
336 return java.
lang.Byte.valueOf((
byte)0);
340 return java.
lang.Character.valueOf((
char)0);
344 return java.
lang.Short.valueOf((
short)0);
348 return java.
lang.Integer.valueOf(0);
360 return java.
lang.Double.valueOf(0D);
362 else if (mw.ReturnType == Context.
JavaBase.TypeOfJavaLangString)
366 else if (mw.ReturnType == Context.
JavaBase.TypeOfJavaLangClass)
368 return (
java.
lang.Class)typeof(ikvm.@
internal.__unspecified);
370 else if (mw.ReturnType is EnumEnumJavaType)
372 EnumEnumJavaType eetw = (EnumEnumJavaType)mw.ReturnType;
373 return eetw.GetUnspecifiedValue();
375 else if (mw.ReturnType.IsArray)
377 return Array.CreateInstance(mw.ReturnType.TypeAsArrayType, 0);
386 internal override RuntimeJavaType DeclaringTypeWrapper => Context.ClassLoaderFactory.GetJavaTypeFromType(attributeType);
388 internal override Type TypeAsTBD => fakeType;
390 internal override RuntimeJavaType[] InnerClasses => innerClasses ??= GetInnerClasses();
392 RuntimeJavaType[] GetInnerClasses()
394 List<RuntimeJavaType> list =
new List<RuntimeJavaType>();
395 AttributeUsageAttribute attr = GetAttributeUsage();
396 if ((attr.ValidOn & AttributeTargets.ReturnValue) != 0)
398 list.Add(ClassLoader.RegisterInitiatingLoader(
new ReturnValueAnnotationJavaType(Context,
this)));
400 if (attr.AllowMultiple)
402 list.Add(ClassLoader.RegisterInitiatingLoader(
new MultipleAnnotationJavaType(Context,
this)));
404 return list.ToArray();
407 internal override bool IsFakeTypeContainer =>
true;
409 AttributeUsageAttribute GetAttributeUsage()
411 AttributeTargets validOn = AttributeTargets.All;
412 bool allowMultiple =
false;
413 bool inherited =
true;
414 foreach (CustomAttributeData cad
in CustomAttributeData.GetCustomAttributes(attributeType))
416 if (cad.Constructor.DeclaringType == Context.
Resolver.ResolveCoreType(typeof(AttributeUsageAttribute).FullName).AsReflection())
418 if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == Context.
Resolver.ResolveCoreType(typeof(AttributeTargets).FullName).AsReflection())
420 validOn = (AttributeTargets)cad.ConstructorArguments[0].Value;
422 foreach (CustomAttributeNamedArgument cana
in cad.NamedArguments)
424 if (cana.MemberInfo.Name ==
"AllowMultiple")
426 allowMultiple = (bool)cana.TypedValue.Value;
428 else if (cana.MemberInfo.Name ==
"Inherited")
430 inherited = (bool)cana.TypedValue.Value;
435 AttributeUsageAttribute attr =
new AttributeUsageAttribute(validOn);
436 attr.AllowMultiple = allowMultiple;
437 attr.Inherited = inherited;
441#if !IMPORTER && !FIRST_PASS && !EXPORTER
442 internal override object[] GetDeclaredAnnotations()
445 AttributeTargets validOn = GetAttributeUsage().ValidOn;
446 List<
java.
lang.annotation.ElementType> targets =
new List<
java.
lang.annotation.ElementType>();
447 if ((validOn & (AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0)
449 targets.Add(
java.
lang.annotation.ElementType.TYPE);
451 if ((validOn & AttributeTargets.Constructor) != 0)
453 targets.Add(
java.
lang.annotation.ElementType.CONSTRUCTOR);
455 if ((validOn & AttributeTargets.Field) != 0)
457 targets.Add(
java.
lang.annotation.ElementType.FIELD);
459 if ((validOn & AttributeTargets.Method) != 0)
461 targets.Add(
java.
lang.annotation.ElementType.METHOD);
463 if ((validOn & AttributeTargets.Parameter) != 0)
465 targets.Add(
java.
lang.annotation.ElementType.PARAMETER);
467 java.util.HashMap targetMap =
new java.
util.HashMap();
468 targetMap.put(
"value", targets.ToArray());
469 java.util.HashMap retentionMap =
new java.
util.HashMap();
470 retentionMap.put(
"value",
java.
lang.annotation.RetentionPolicy.RUNTIME);
471 return new object[] {
472 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)),
473 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))
478 sealed class AttributeAnnotation : Annotation
487 internal AttributeAnnotation(
Type type)
492 CustomAttributeBuilder MakeCustomAttributeBuilder(RuntimeClassLoader loader,
object annotation)
494 object[] arr = (
object[])annotation;
497 object ctorArg =
null;
498 GetConstructors(loader.Context, type, out defCtor, out singleOneArgCtor);
499 List<PropertyInfo> properties =
new List<PropertyInfo>();
500 List<object> propertyValues =
new List<object>();
501 List<FieldInfo> fields =
new List<FieldInfo>();
502 List<object> fieldValues =
new List<object>();
503 for (
int i = 2; i < arr.Length; i += 2)
505 string name = (string)arr[i];
506 if (name ==
"value" && singleOneArgCtor !=
null)
508 ctorArg =
ConvertValue(loader, singleOneArgCtor.GetParameters()[0].ParameterType, arr[i + 1]);
512 PropertyInfo pi = type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
516 propertyValues.Add(
ConvertValue(loader, pi.PropertyType, arr[i + 1]));
520 FieldInfo fi = type.GetField(name, BindingFlags.Public | BindingFlags.Instance);
524 fieldValues.Add(
ConvertValue(loader, fi.FieldType, arr[i + 1]));
529 if (ctorArg ==
null && defCtor ==
null)
533 return new CustomAttributeBuilder(ctorArg ==
null ? defCtor : singleOneArgCtor,
534 ctorArg ==
null ?
new object[0] :
new object[] { ctorArg },
535 properties.ToArray(),
536 propertyValues.ToArray(),
538 fieldValues.ToArray());
541 internal override void Apply(RuntimeClassLoader loader, TypeBuilder tb,
object annotation)
543 if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.
Runtime.InteropServices.StructLayoutAttribute).FullName).AsReflection() && tb.BaseType != loader.Context.Types.Object)
548 loader.Diagnostics.IgnoredCustomAttribute(type.FullName, $
"Type '{tb.FullName}' does not extend cli.System.Object");
550 loader.Diagnostics.GenericRuntimeError($
"StructLayoutAttribute cannot be applied to {tb.FullName}, because it does not directly extend cli.System.Object");
555 tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
558 internal override void Apply(RuntimeClassLoader loader, MethodBuilder mb,
object annotation)
560 mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
563 internal override void Apply(RuntimeClassLoader loader, FieldBuilder fb,
object annotation)
565 fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
568 internal override void Apply(RuntimeClassLoader loader, ParameterBuilder pb,
object annotation)
572 if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.
Runtime.InteropServices.DefaultParameterValueAttribute).FullName).AsReflection())
573 throw new NotImplementedException();
575 pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
578 internal override void Apply(RuntimeClassLoader loader, AssemblyBuilder ab,
object annotation)
581 if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.
Runtime.
CompilerServices.TypeForwardedToAttribute).FullName).AsReflection())
583 ab.__AddTypeForwarder((
Type)
ConvertValue(loader, loader.Context.Types.Type, ((
object[])annotation)[3]));
585 else if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyVersionAttribute).FullName).AsReflection())
587 string str = (string)
ConvertValue(loader, loader.Context.Types.String, ((
object[])annotation)[3]);
591 ab.__SetAssemblyVersion(version);
595 loader.Diagnostics.InvalidCustomAttribute(type.FullName,
"The version '" + str +
"' is invalid.");
598 else if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyCultureAttribute).FullName).AsReflection())
600 string str = (string)
ConvertValue(loader, loader.Context.Types.String, ((
object[])annotation)[3]);
603 ab.__SetAssemblyCulture(str);
606 else if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyDelaySignAttribute).FullName).AsReflection()
607 || type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyKeyFileAttribute).FullName).AsReflection()
608 || type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyKeyNameAttribute).FullName).AsReflection())
610 loader.Diagnostics.IgnoredCustomAttribute(type.FullName,
"Please use the corresponding compiler switch.");
612 else if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyAlgorithmIdAttribute).FullName).AsReflection())
615 throw new NotImplementedException();
617 else if (type == loader.Context.Resolver.ResolveCoreType(typeof(
System.Reflection.AssemblyFlagsAttribute).FullName).AsReflection())
620 throw new NotImplementedException();
624 ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
627 ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
631 internal override void Apply(RuntimeClassLoader loader, PropertyBuilder pb,
object annotation)
633 pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
636 internal override bool IsCustomAttribute =>
true;
640 internal override Annotation Annotation =>
new AttributeAnnotation(attributeType);
642 internal override AttributeTargets AttributeTargets => GetAttributeUsage().ValidOn;
IKVM.Reflection.Type Type
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.FieldInfo FieldInfo
IKVM.Reflection.PropertyInfo PropertyInfo
IKVM.Reflection.ParameterInfo ParameterInfo
static object ConvertValue(RuntimeClassLoader loader, Type targetType, object obj)
Types Types
Gets the Types associated with this instance of the runtime.
RuntimePrimitiveJavaTypeFactory PrimitiveJavaTypeFactory
Gets the RuntimePrimitiveJavaTypeFactory associated with this instance of the runtime.
ISymbolResolver Resolver
Gets the ISymbolResolver associated with this instance of the runtime.
CoreClasses JavaBase
Gets the CoreClasses associated with this instance of the runtime.
Represents the context of an import operation outputing a single assembly.
MemberFlags
Describes various options applied to a member.