/// <summary> /// Create the current type as class definition. /// </summary> public virtual void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage) { // Find xfield xField = XBuilder.AsFieldDefinition(compiler.Module, field); // Create field definition dfield = new Dot42.DexLib.FieldDefinition(); dfield.Name = NameConverter.GetConvertedName(field); AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); // Set access flags SetAccessFlags(dfield, field); // Give warning if static in generic class. // This could of cause also be handled automagically be the compiler, // with mixture of whats done in the Interlocked converter and whats // done in the GenericInstanceConverter. if (field.IsStatic && declaringType.IsGenericClass) { if (!field.HasSuppressMessageAttribute("StaticFieldInGenericType") && !field.DeclaringType.HasSuppressMessageAttribute("StaticFieldInGenericType")) { string msg; if (field.Name.Contains("CachedAnonymousMethodDelegate")) { msg = "The compiler generated a static field '{0}' in generic type '{1}'. This is not supported " + "in Dot42 if the anonymous delegate accesses a generic class parameter. A workaround " + "is to convert the anonymous static delegate to a normal method.\n"; } else { msg = "Static field '{0}' in generic type {1}: All generic instances will share " + "the same static field, contrary on how CLR operates. A workaround is to " + "use ConcurrentDictionaries to access the values dependent on the type.\n"; } msg += "You can suppress this warning with a [SuppressMessage(\"dot42\"," + " \"StaticFieldInGenericType\")] attribute, either on the field or on the class."; var body = field.DeclaringType.Methods.Select(m => m.Body) .FirstOrDefault(m => m != null && m.Instructions.Any(i => i.SequencePoint(m) != null)); if (body != null) { var seqPoint = body.Instructions.Select(i => i.SequencePoint(body)).First(i => i != null); DLog.Warning(DContext.CompilerILConverter, seqPoint.Document.Url, seqPoint.StartColumn, seqPoint.StartLine, msg, field.Name, declaringType.FullName); } else { DLog.Warning(DContext.CompilerILConverter, msg, field.Name, declaringType.FullName); } } } }
/// <summary> /// Create the current type as class definition. /// </summary> public virtual void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage) { // Find xfield xField = XBuilder.AsFieldDefinition(compiler.Module, field); // Create field definition dfield = new Dot42.DexLib.FieldDefinition(); dfield.Name = NameConverter.GetConvertedName(field); AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); // Set access flags SetAccessFlags(dfield, field); // Give warning if static in generic class. // This could of cause also be handled automagically be the compiler, // with mixture of whats done in the Interlocked converter and whats // done in the GenericInstanceConverter. if (field.IsStatic && declaringType.IsGenericClass) { if (!field.HasSuppressMessageAttribute("StaticFieldInGenericType") && !field.DeclaringType.HasSuppressMessageAttribute("StaticFieldInGenericType")) { string msg; if (field.Name.Contains("CachedAnonymousMethodDelegate")) msg = "The compiler generated a static field '{0}' in generic type '{1}'. This is not supported " + "in Dot42 if the anonymous delegate accesses a generic class parameter. A workaround " + "is to convert the anonymous static delegate to a normal method.\n"; else msg = "Static field '{0}' in generic type {1}: All generic instances will share " + "the same static field, contrary on how CLR operates. A workaround is to " + "use ConcurrentDictionaries to access the values dependent on the type.\n"; msg += "You can suppress this warning with a [SuppressMessage(\"dot42\"," + " \"StaticFieldInGenericType\")] attribute, either on the field or on the class."; var body = field.DeclaringType.Methods.Select(m => m.Body) .FirstOrDefault(m => m != null && m.Instructions.Any(i => i.SequencePoint != null)); if (body != null) { var seqPoint = body.Instructions.Select(i=>i.SequencePoint).First(i => i != null); DLog.Warning(DContext.CompilerILConverter, seqPoint.Document.Url, seqPoint.StartColumn, seqPoint.StartLine, msg, field.Name, declaringType.FullName); } else { DLog.Warning(DContext.CompilerILConverter, msg, field.Name, declaringType.FullName); } } } }
/// <summary> /// Create the current type as class definition. /// </summary> public void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage) { // Find xfield xField = XBuilder.AsFieldDefinition(compiler.Module, field); // Create field definition dfield = new Dot42.DexLib.FieldDefinition(); dfield.Name = NameConverter.GetConvertedName(field); AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); // Set access flags SetAccessFlags(dfield, field); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build ctors foreach (var baseCtor in GetBaseClassCtors()) { // TODO: does this make sense? after all, we derive from object. // probalby one should just remove this code, and generate a // defaul constructor. var prototype = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, null, baseCtor); var ctor = new MethodDefinition(Class, "<init>", prototype); ctor.AccessFlags = AccessFlags.Public | AccessFlags.Constructor; Class.Methods.Add(ctor); // Create ctor body var ctorBody = CreateCtorBody(prototype); targetPackage.Record(new CompiledMethod { DexMethod = ctor, RLBody = ctorBody }); } // build original type field // Create field definition // NOTE: at the moment the underlying type is both defined as a type and in the annotation. // remove one or the other when we have determined which is the better way. var dfield = new Dot42.DexLib.FieldDefinition(); dfield.Owner = Class; dfield.Name = "underlying$"; dfield.IsSynthetic = true; dfield.IsFinal = true; dfield.IsStatic = true; dfield.IsPublic = true; dfield.Type = Compiler.Module.TypeSystem.Type.GetClassReference(targetPackage); dfield.Value = _underlyingBuilder.Class; Class.Fields.Add(dfield); }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build ctors foreach (var baseCtor in GetBaseClassCtors()) { // TODO: does this make sense? after all, we derive from object. // probalby one should just remove this code, and generate a // defaul constructor. var prototype = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, null, baseCtor); var ctor = new MethodDefinition(Class, "<init>", prototype); ctor.AccessFlags = AccessFlags.Public | AccessFlags.Constructor; Class.Methods.Add(ctor); // Create ctor body var ctorBody = CreateCtorBody(prototype); targetPackage.Record(new CompiledMethod { DexMethod = ctor, RLBody = ctorBody }); } // build original type field // Create field definition // NOTE: at the moment the underlying type is both defined as a type and in the annotation. // remove one or the other when we have determined which is the better way. var dfield = new Dot42.DexLib.FieldDefinition(); dfield.Owner = Class; dfield.Name = "underlying$"; dfield.IsSynthetic = true; dfield.IsFinal = true; dfield.IsStatic= true; dfield.IsPublic = true; dfield.Type = Compiler.Module.TypeSystem.Type.GetClassReference(targetPackage); dfield.Value = _underlyingBuilder.Class; Class.Fields.Add(dfield); }