diff options
author | jfrijters <jfrijters> | 2014-07-09 16:25:08 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2014-07-09 16:25:08 +0400 |
commit | e714b27336d2382f7c365c16579a687aa4ad5136 (patch) | |
tree | b7f6bc3bfa9c0482e70dda43ce1aac84246643ed | |
parent | bb2d12a8a4a7c1070ac19499170a26e96252704c (diff) |
Added method and field reflection support for lambda classes.
-rw-r--r-- | runtime/LambdaMetafactory.cs | 22 | ||||
-rw-r--r-- | runtime/TypeWrapper.cs | 53 |
2 files changed, 61 insertions, 14 deletions
diff --git a/runtime/LambdaMetafactory.cs b/runtime/LambdaMetafactory.cs index 7ea26157..f2a5bc81 100644 --- a/runtime/LambdaMetafactory.cs +++ b/runtime/LambdaMetafactory.cs @@ -403,7 +403,7 @@ namespace IKVM.Internal { attr |= FieldAttributes.InitOnly; } - capturedFields[i] = tb.DefineField("c" + i, capturedTypes[i], attr); + capturedFields[i] = tb.DefineField("arg$" + (i + 1), capturedTypes[i], attr); } // constructor @@ -479,7 +479,11 @@ namespace IKVM.Internal private static void EmitDispatch(DynamicTypeWrapper.FinishContext context, TypeWrapper[] args, TypeBuilder tb, MethodWrapper interfaceMethod, TypeWrapper[] implParameters, ClassFile.ConstantPoolItemMethodHandle implMethod, ClassFile.ConstantPoolItemMethodType instantiatedMethodType, FieldBuilder[] capturedFields) { - MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + MethodBuilder mb = interfaceMethod.GetDefineMethodHelper().DefineMethod(context.TypeWrapper, tb, interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + if (interfaceMethod.Name != interfaceMethod.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)interfaceMethod.GetMethod()); + } CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0; i < capturedFields.Length; i++) { @@ -680,17 +684,27 @@ namespace IKVM.Internal private static void AddDefaultInterfaceMethods(DynamicTypeWrapper.FinishContext context, MethodWrapper[] methodList, TypeBuilder tb) { + // we use special name to hide these from Java reflection + const MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName; TypeWrapperFactory factory = context.TypeWrapper.GetClassLoader().GetTypeWrapperFactory(); foreach (MethodWrapper mw in methodList) { if (!mw.IsAbstract) { - MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); + if (mw.Name != mw.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + } DynamicTypeWrapper.FinishContext.EmitCallDefaultInterfaceMethod(mb, mw); } else if (IsObjectMethod(mw)) { - MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.RealName, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final); + MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(factory, tb, mw.Name, attr); + if (mw.Name != mw.RealName) + { + tb.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); + } CodeEmitter ilgen = CodeEmitter.Create(mb); for (int i = 0, count = mw.GetParameters().Length; i <= count; i++) { diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs index e85879ac..8efd4d69 100644 --- a/runtime/TypeWrapper.cs +++ b/runtime/TypeWrapper.cs @@ -4989,13 +4989,13 @@ namespace IKVM.Internal ?? ClassLoaderWrapper.GetWrapperFromType(property.PropertyType); } - private static TypeWrapper GetFieldTypeWrapper(FieldInfo field) + internal static TypeWrapper GetFieldTypeWrapper(FieldInfo field) { return TypeWrapperFromModOpt(field.GetOptionalCustomModifiers()) ?? ClassLoaderWrapper.GetWrapperFromType(field.FieldType); } - private static TypeWrapper GetParameterTypeWrapper(ParameterInfo param) + internal static TypeWrapper GetParameterTypeWrapper(ParameterInfo param) { TypeWrapper tw = TypeWrapperFromModOpt(param.GetOptionalCustomModifiers()); if (tw != null) @@ -5760,18 +5760,51 @@ namespace IKVM.Internal protected override void LazyPublishMembers() { - MethodInfo mi = type.GetMethod("writeReplace", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, Type.EmptyTypes, null); - if (mi != null) + List<MethodWrapper> methods = new List<MethodWrapper>(); + foreach (MethodInfo mi in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { - SetMethods(new MethodWrapper[] { - new TypicalMethodWrapper(this, "writeReplace", "()Ljava.lang.Object;", mi, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Private, MemberFlags.None) - }); + if (mi.IsSpecialName) + { + // we use special name to hide default methods + } + else if (mi.IsPublic) + { + TypeWrapper returnType; + TypeWrapper[] parameterTypes; + string signature; + GetSig(mi, out returnType, out parameterTypes, out signature); + methods.Add(new TypicalMethodWrapper(this, mi.Name, signature, mi, returnType, parameterTypes, Modifiers.Public, MemberFlags.None)); + } + else if (mi.Name == "writeReplace") + { + methods.Add(new TypicalMethodWrapper(this, "writeReplace", "()Ljava.lang.Object;", mi, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, + Modifiers.Private | Modifiers.Final, MemberFlags.None)); + } } - else + SetMethods(methods.ToArray()); + List<FieldWrapper> fields = new List<FieldWrapper>(); + foreach (FieldInfo fi in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { - SetMethods(MethodWrapper.EmptyArray); + TypeWrapper fieldType = CompiledTypeWrapper.GetFieldTypeWrapper(fi); + fields.Add(new SimpleFieldWrapper(this, fieldType, fi, fi.Name, fieldType.SigName, new ExModifiers(Modifiers.Private | Modifiers.Final, false))); } - SetFields(FieldWrapper.EmptyArray); + SetFields(fields.ToArray()); + } + + private void GetSig(MethodInfo mi, out TypeWrapper returnType, out TypeWrapper[] parameterTypes, out string signature) + { + returnType = CompiledTypeWrapper.GetParameterTypeWrapper(mi.ReturnParameter); + ParameterInfo[] parameters = mi.GetParameters(); + parameterTypes = new TypeWrapper[parameters.Length]; + System.Text.StringBuilder sb = new System.Text.StringBuilder("("); + for (int i = 0; i < parameters.Length; i++) + { + parameterTypes[i] = CompiledTypeWrapper.GetParameterTypeWrapper(parameters[i]); + sb.Append(parameterTypes[i].SigName); + } + sb.Append(')'); + sb.Append(returnType.SigName); + signature = sb.ToString(); } } } |