internal RemapperTypeWrapper(CompilerClassLoader classLoader, IKVM.Internal.MapXml.Class c, IKVM.Internal.MapXml.Root map) : base((Modifiers)c.Modifiers, c.Name) { this.classLoader = classLoader; this.baseTypeWrapper = GetBaseWrapper(c); classDef = c; bool baseIsSealed = false; shadowType = StaticCompiler.Universe.GetType(c.Shadows, true); classLoader.SetRemappedType(shadowType, this); Type baseType = shadowType; Type baseInterface = null; if(baseType.IsInterface) { baseInterface = baseType; } TypeAttributes attrs = TypeAttributes.Public; if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Interface) == 0) { attrs |= TypeAttributes.Class; if(baseType.IsSealed) { baseIsSealed = true; attrs |= TypeAttributes.Abstract | TypeAttributes.Sealed; } } else { attrs |= TypeAttributes.Interface | TypeAttributes.Abstract; baseType = null; } if((c.Modifiers & IKVM.Internal.MapXml.MapModifiers.Abstract) != 0) { attrs |= TypeAttributes.Abstract; } string name = c.Name.Replace('/', '.'); typeBuilder = classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(name, attrs, baseIsSealed ? Types.Object : baseType); if(c.Attributes != null) { foreach(IKVM.Internal.MapXml.Attribute custattr in c.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, typeBuilder, custattr); } } if(baseInterface != null) { typeBuilder.AddInterfaceImplementation(baseInterface); } if(classLoader.EmitStackTraceInfo) { AttributeHelper.SetSourceFile(typeBuilder, Path.GetFileName(classLoader.options.remapfile)); } if(baseIsSealed) { AttributeHelper.SetModifiers(typeBuilder, (Modifiers)c.Modifiers, false); } if(c.scope == IKVM.Internal.MapXml.Scope.Public) { // FXBUG we would like to emit an attribute with a Type argument here, but that doesn't work because // of a bug in SetCustomAttribute that causes type arguments to be serialized incorrectly (if the type // is in the same assembly). Normally we use AttributeHelper.FreezeDry to get around this, but that doesn't // work in this case (no attribute is emitted at all). So we work around by emitting a string instead AttributeHelper.SetRemappedClass(classLoader.assemblyBuilder, name, shadowType); AttributeHelper.SetRemappedType(typeBuilder, shadowType); } List<MethodWrapper> methods = new List<MethodWrapper>(); if(c.Constructors != null) { foreach(IKVM.Internal.MapXml.Constructor m in c.Constructors) { methods.Add(new RemappedConstructorWrapper(this, m)); } } if(c.Methods != null) { foreach(IKVM.Internal.MapXml.Method m in c.Methods) { methods.Add(new RemappedMethodWrapper(this, m, map, false)); } } // add methods from our super classes (e.g. Throwable should have Object's methods) if(!this.IsFinal && !this.IsInterface && this.BaseTypeWrapper != null) { foreach(MethodWrapper mw in BaseTypeWrapper.GetMethods()) { RemappedMethodWrapper rmw = mw as RemappedMethodWrapper; if(rmw != null && (rmw.IsPublic || rmw.IsProtected)) { if(!FindMethod(methods, rmw.Name, rmw.Signature)) { methods.Add(new RemappedMethodWrapper(this, rmw.XmlMethod, map, true)); } } } } SetMethods(methods.ToArray()); }
protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods) { Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses(); if(mapxml != null) { IKVM.Internal.MapXml.Class clazz; if(mapxml.TryGetValue(classFile.Name, out clazz)) { if(clazz.Attributes != null) { PublishAttributes(typeBuilder, clazz); } if(clazz.Properties != null) { PublishProperties(typeBuilder, clazz); } if(clazz.Fields != null) { foreach(IKVM.Internal.MapXml.Field field in clazz.Fields) { if(field.Attributes != null) { foreach(FieldWrapper fw in fields) { if(fw.Name == field.Name && fw.Signature == field.Sig) { FieldBuilder fb = fw.GetField() as FieldBuilder; if(fb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in field.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, fb, attr); } } } } } } } if(clazz.Constructors != null) { // HACK this isn't the right place to do this, but for now it suffices foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) { // are we adding a new constructor? if(GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null) { if(constructor.body == null) { Console.Error.WriteLine("Error: Constructor {0}.<init>{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig); continue; } bool setmodifiers = false; MethodAttributes attribs = 0; MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs); Type returnType; Type[] parameterTypes; MapSignature(constructor.Sig, out returnType, out parameterTypes); MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes); if(setmodifiers) { AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false); } CompilerClassLoader.AddDeclaredExceptions(cb, constructor.throws); CodeEmitter ilgen = CodeEmitter.Create(cb); constructor.Emit(classLoader, ilgen); ilgen.DoEmit(); if(constructor.Attributes != null) { foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, cb, attr); } } } } foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) { if(constructor.Attributes != null) { foreach(MethodWrapper mw in methods) { if(mw.Name == "<init>" && mw.Signature == constructor.Sig) { MethodBuilder mb = mw.GetMethod() as MethodBuilder; if(mb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } } } } if(clazz.Methods != null) { // HACK this isn't the right place to do this, but for now it suffices foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) { // are we adding a new method? if(GetMethodWrapper(method.Name, method.Sig, false) == null) { if(method.body == null) { Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig); continue; } bool setmodifiers = false; MethodAttributes attribs = method.MethodAttributes; MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs); Type returnType; Type[] parameterTypes; MapSignature(method.Sig, out returnType, out parameterTypes); MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes); if(setmodifiers) { AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false); } if(method.@override != null) { MethodWrapper mw = GetClassLoader().LoadClassByDottedName([email protected]).GetMethodWrapper([email protected], method.Sig, true); mw.Link(); typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); } CompilerClassLoader.AddDeclaredExceptions(mb, method.throws); CodeEmitter ilgen = CodeEmitter.Create(mb); method.Emit(classLoader, ilgen); ilgen.DoEmit(); if(method.Attributes != null) { foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) { if(method.Attributes != null) { foreach(MethodWrapper mw in methods) { if(mw.Name == method.Name && mw.Signature == method.Sig) { MethodBuilder mb = mw.GetMethod() as MethodBuilder; if(mb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } } } } if(clazz.Interfaces != null) { foreach(IKVM.Internal.MapXml.Interface iface in clazz.Interfaces) { TypeWrapper tw = GetClassLoader().LoadClassByDottedName(iface.Name); // NOTE since this interface won't be part of the list in the ImplementAttribute, // it won't be visible from Java that the type implements this interface. typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType); if(iface.Methods != null) { foreach(IKVM.Internal.MapXml.Method m in iface.Methods) { MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false); if(mw == null) { throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name); } mw.Link(); MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride); AttributeHelper.HideFromJava(mb); typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); CodeEmitter ilgen = CodeEmitter.Create(mb); m.Emit(classLoader, ilgen); ilgen.DoEmit(); } } } } } } }