/// <summary> /// Default ctor /// </summary> private MethodBuilder(MethodDefinition javaMethod, TypeBuilder declaringTypeBuilder, SignedByteMode signedByteMode) { this.javaMethod = javaMethod; this.declaringTypeBuilder = declaringTypeBuilder; this.signedByteMode = signedByteMode; this.addJavaPrefix = signedByteMode == SignedByteMode.HasUnsignedPartnerOnlyInReturnType; }
/// <summary> /// Gets a mapping. /// Throws an error if not found. /// </summary> public NetMethodDefinition Get(MethodDefinition javaMethod) { NetMethodDefinition result; if (map.TryGetValue(javaMethod, out result)) return result; throw new ArgumentOutOfRangeException(string.Format("No matching .NET method for {0}", javaMethod)); }
/// <summary> /// Default ctor /// </summary> private MethodBuilder(MethodDefinition javaMethod, TypeBuilder declaringTypeBuilder, bool convertSignedBytes, bool addJavaPrefix) { this.javaMethod = javaMethod; this.declaringTypeBuilder = declaringTypeBuilder; this.convertSignedBytes = convertSignedBytes; this.addJavaPrefix = addJavaPrefix; }
/// <summary> /// Resolve the method into a java method definition. /// </summary> public JavaMethodDefinition Resolve(ClassFile declaringClass) { if (resolved == null) { // Load the class resolved = BuildMethod(declaringClass); } return(resolved); }
/// <summary> /// Should the given method be implemented? /// </summary> protected override bool ShouldImplement(MethodDefinition method, TargetFramework target) { if (method.Name == "getLong") { if (method.Descriptor == "(Ljava/lang/String;Ljava/lang/Long;)Ljava/lang/Long;") return false; } return base.ShouldImplement(method, target); }
/// <summary> /// Is the given method a bridge method that calls the given target method? /// </summary> public static bool IsBridgeFor(this MethodDefinition method, MethodDefinition target) { if ((!method.IsBridge) || (method == target)) return false; if ((method.Name != target.Name) || (method.Parameters.Count != target.Parameters.Count)) return false; if (method.Body == null) return false; return method.Body.Instructions.Select(x => x.Operand).OfType<ConstantPoolMethodRef>().Any(x => (x.Descriptor == target.Descriptor) && (x.Name == target.Name)); }
/// <summary> /// Default ctor /// </summary> public AstBuilder(XModule module, MethodDefinition methodDef, XTypeDefinition declaringType, bool optimize) { this.module = module; typeSystem = module.TypeSystem; this.methodDef = methodDef; this.declaringType = declaringType; this.optimize = optimize; codeAttr = methodDef.Attributes.OfType<CodeAttribute>().FirstOrDefault(); validExceptionHandlers = (codeAttr != null) ? codeAttr.ExceptionHandlers.Where(IsValid).ToList() : null; }
/// <summary> /// Default ctor /// </summary> public AstBuilder(XModule module, MethodDefinition methodDef, XTypeDefinition declaringType, bool optimize) { this.module = module; typeSystem = module.TypeSystem; this.methodDef = methodDef; this.declaringType = declaringType; this.optimize = optimize; codeAttr = methodDef.Attributes.OfType <CodeAttribute>().FirstOrDefault(); validExceptionHandlers = (codeAttr != null) ? codeAttr.ExceptionHandlers.Where(IsValid).ToList() : null; }
/// <summary> /// Should the given method be implemented? /// </summary> protected override bool ShouldImplement(MethodDefinition method, TargetFramework target) { if (method.Name == "getInteger") { if (method.Descriptor == "(Ljava/lang/String;Ljava/lang/Integer;)Ljava/lang/Integer;") { return(false); } } return(base.ShouldImplement(method, target)); }
/// <summary> /// Create method builders for the given method. /// </summary> internal static IEnumerable<MethodBuilder> Create(MethodDefinition javaMethod, TypeBuilder declaringTypeBuilder) { bool onlyInReturnType; var convertSignedBytes = ContainsSignedByte(javaMethod, out onlyInReturnType) && !AvoidConvertSignedBytes(javaMethod); if (onlyInReturnType && javaMethod.DeclaringClass.IsInterface) { yield return new MethodBuilder(javaMethod, declaringTypeBuilder, true, false); } else { var addJavaPrefix = convertSignedBytes && onlyInReturnType; yield return new MethodBuilder(javaMethod, declaringTypeBuilder, false, addJavaPrefix); if (convertSignedBytes) yield return new MethodBuilder(javaMethod, declaringTypeBuilder, true, false); } }
/// <summary> /// Are the given methods the same wrt name and parameters? /// </summary> private static bool AreSame(this MethodDefinition method, MethodDefinition other) { if (method.Name != other.Name) return false; return (method.Descriptor == other.Descriptor) || (Descriptors.StripMethodReturnType(method.Descriptor) == Descriptors.StripMethodReturnType(other.Descriptor)); }
/// <summary> /// Default ctor /// </summary> public JavaMethodDefinition(XTypeDefinition declaringType, MethodDefinition method) : base(declaringType) { this.method = method; }
/// <summary> /// Resolve the method into a java method definition. /// </summary> public JavaMethodDefinition Resolve(ClassFile declaringClass) { if (resolved == null) { // Load the class resolved = BuildMethod(declaringClass); } return resolved; }
/// <summary> /// Update the attributes of the given method /// </summary> public override MethodAttributes GetMethodAttributes(MethodDefinition method, MethodAttributes methodAttributes) { return (base.GetMethodAttributes(method, methodAttributes) | MethodAttributes.Final); }
/// <summary> /// Create method builders for the given method. /// </summary> internal static IEnumerable<MethodBuilder> Create(MethodDefinition javaMethod, TypeBuilder declaringTypeBuilder) { bool onlyInReturnType; var convertSignedBytes = ContainsSignedByte(javaMethod, out onlyInReturnType) && !AvoidConvertSignedBytes(javaMethod); if (convertSignedBytes && (javaMethod.DeclaringClass.IsInterface || javaMethod.IsAbstract)) { yield return new MethodBuilder(javaMethod, declaringTypeBuilder, SignedByteMode.ConvertWithoutPartner); } else { var signedByteMode = !convertSignedBytes ? SignedByteMode.None : onlyInReturnType ? SignedByteMode.HasUnsignedPartnerOnlyInReturnType : SignedByteMode.HasUnsignedPartner; yield return new MethodBuilder(javaMethod, declaringTypeBuilder, signedByteMode); if (convertSignedBytes) yield return new MethodBuilder(javaMethod, declaringTypeBuilder, SignedByteMode.Convert); } }
/// <summary> /// Default ctor /// </summary> public JavaMethodDefinitionNode(MethodDefinition methodDef) { this.methodDef = methodDef; Text = methodDef.Name; ImageIndex = 6; }
/// <summary> /// Read a Code attribute /// </summary> private CodeAttribute ReadCodeAttribute(MethodDefinition method, ConstantPool cp) { var maxStack = stream.ReadU2(); var maxLocals = stream.ReadU2(); var codeLength = (int)stream.ReadU4(); var code = new byte[codeLength]; stream.Read(code, 0, codeLength); var result = new CodeAttribute(method, cp, maxStack, maxLocals, code); var ecount = stream.ReadU2(); for (var i = 0; i < ecount; i++) { var startPC = stream.ReadU2(); var endPC = stream.ReadU2(); var handlerPC = stream.ReadU2(); var catchTypeIndex = stream.ReadU2(); var catchType = (catchTypeIndex != 0) ? cp.GetEntry<ConstantPoolClass>(catchTypeIndex).Type : null; result.Add(new ExceptionHandler(result, startPC, endPC, handlerPC, catchType)); } ReadAttributes(cp, result); return result; }
protected override bool ShouldImplement(MethodDefinition method, TargetFramework target) { return false; }
/// <summary> /// Convert an Java method reference to an XMethodReference. /// </summary> public static XMethodDefinition AsMethodDefinition(XModule module, MethodDefinition method) { return AsTypeReference(module, method.DeclaringClass, XTypeUsageFlags.DeclaringType).Resolve().GetByOriginalMethod(method); }
/// <summary> /// Clone this definition for use in a given other class. /// </summary> public MethodDefinition CloneTo(ClassFile otherClass) { var clone = new MethodDefinition(otherClass, accessFlags, Name, descriptor, null); clone.signature = signature; return clone; }
/// <summary> /// Read the header /// </summary> internal void ReadHeader(ClassFile cf) { var magic = stream.ReadU4(); if (magic != ClassFile.Magic) throw new Dot42Exception("Invalid magic"); cf.MinorVersion = stream.ReadU2(); cf.MajorVersion = stream.ReadU2(); var cpCount = stream.ReadU2(); var cp = new ConstantPool(cpCount, cf.Loader); for (var i = 1; i < cpCount; i++) { var tag = (ConstantPoolTags) stream.ReadU1(); ConstantPoolEntry entry; int tmp; switch (tag) { case ConstantPoolTags.Class: entry = new ConstantPoolClass(cp, stream.ReadU2()); break; case ConstantPoolTags.Fieldref: tmp = stream.ReadU2(); entry = new ConstantPoolFieldRef(cp, tmp, stream.ReadU2()); break; case ConstantPoolTags.Methodref: tmp = stream.ReadU2(); entry = new ConstantPoolMethodRef(cp, tmp, stream.ReadU2()); break; case ConstantPoolTags.InterfaceMethodref: tmp = stream.ReadU2(); entry = new ConstantPoolInterfaceMethodRef(cp, tmp, stream.ReadU2()); break; case ConstantPoolTags.String: entry = new ConstantPoolString(cp, stream.ReadU2()); break; case ConstantPoolTags.Integer: entry = new ConstantPoolInteger(cp, stream.ReadS4()); break; case ConstantPoolTags.Float: entry = new ConstantPoolFloat(cp, stream.ReadF4()); break; case ConstantPoolTags.Long: entry = new ConstantPoolLong(cp, stream.ReadS8()); break; case ConstantPoolTags.Double: entry = new ConstantPoolDouble(cp, stream.ReadF8()); break; case ConstantPoolTags.NameAndType: tmp = stream.ReadU2(); entry = new ConstantPoolNameAndType(cp, tmp, stream.ReadU2()); break; case ConstantPoolTags.Utf8: tmp = stream.ReadU2(); entry = new ConstantPoolUtf8(cp, stream.ReadUTF8(tmp)); break; default: throw new Dot42Exception("Unknown constant pool tag: " + (int)tag); } cp[i] = entry; if ((tag == ConstantPoolTags.Double) || (tag == ConstantPoolTags.Long)) i++; } cf.ClassAccessFlags = (ClassAccessFlags) stream.ReadU2(); var index = stream.ReadU2(); cf.ClassName = cp.GetEntry<ConstantPoolClass>(index).Name; index = stream.ReadU2(); cf.SuperClass = (index == 0) ? null : new ObjectTypeReference(cp.GetEntry<ConstantPoolClass>(index).Name, null); // Interfaces var icount = stream.ReadU2(); var interfaces = new string[icount]; for (var i = 0; i < icount; i++) { index = stream.ReadU2(); interfaces[i] = cp.GetEntry<ConstantPoolClass>(index).Name; } cf.Interfaces = interfaces.Select(x => new ObjectTypeReference(x, null)).ToArray(); // Fields var fcount = stream.ReadU2(); for (var i = 0; i < fcount; i++) { var accessFlags = (FieldAccessFlags) stream.ReadU2(); var nameIndex = stream.ReadU2(); var descriptorIndex = stream.ReadU2(); var name = cp.GetEntry<ConstantPoolUtf8>(nameIndex).Value; var descriptor = cp.GetEntry<ConstantPoolUtf8>(descriptorIndex).Value; var field = new FieldDefinition(cf, accessFlags, name, descriptor, null); ReadAttributes(cp, field); cf.Fields.Add(field); } // Methods var mcount = stream.ReadU2(); for (var i = 0; i < mcount; i++) { var accessFlags = (MethodAccessFlags)stream.ReadU2(); var nameIndex = stream.ReadU2(); var descriptorIndex = stream.ReadU2(); var name = cp.GetEntry<ConstantPoolUtf8>(nameIndex).Value; var descriptor = cp.GetEntry<ConstantPoolUtf8>(descriptorIndex).Value; var method = new MethodDefinition(cf, accessFlags, name, descriptor, null); ReadAttributes(cp, method); cf.Methods.Add(method); } // Attributes ReadAttributes(cp, cf); }
/// <summary> /// Create type attributes /// </summary> private static MethodAttributes GetAttributes(NetTypeDefinition declaringType, NetMethodDefinition method, MethodDefinition javaMethod, string methodName, TypeNameMap typeNameMap) { var result = (MethodAttributes) 0; var isStatic = javaMethod.IsStatic; if (javaMethod.IsPublic) result |= MethodAttributes.Public; else if (javaMethod.IsProtected) result |= MethodAttributes.FamORAssem; else if (javaMethod.IsPrivate) result |= MethodAttributes.Private; else if (javaMethod.IsPackagePrivate) result |= MethodAttributes.Assembly; if (isStatic) result |= MethodAttributes.Static; if (javaMethod.IsAbstract) result |= MethodAttributes.Abstract; if (declaringType.IsInterface) result |= MethodAttributes.Abstract; if ((!javaMethod.IsFinal) && !isStatic && (methodName != ".ctor") && (!declaringType.IsStruct)) { result |= MethodAttributes.Virtual; } else { result |= MethodAttributes.Final; } if (methodName == ".cctor") { result |= MethodAttributes.Static; } if (declaringType.IsSealed) { result &= ~MethodAttributes.Virtual; } return result; }
/// <summary> /// Add the given mapping /// </summary> public void Add(MethodDefinition javaMethod, NetMethodDefinition netMethod) { map.Add(javaMethod, netMethod); }
/// <summary> /// Does the given method contain a parameter or return type that contains a signed byte. /// </summary> private static bool ContainsSignedByte(MethodDefinition javaMethod, out bool onlyInReturnType) { onlyInReturnType = false; var result = javaMethod.ReturnType.ContainsSignedByte(); if (javaMethod.Parameters.Any(x => x.ContainsSignedByte())) { result = true; } else if (result) { onlyInReturnType = true; return true; } return result; }
/// <summary> /// Gets a mapping. /// Throws an error if not found. /// </summary> public bool TryGet(MethodDefinition javaMethod, out NetMethodDefinition result) { return map.TryGetValue(javaMethod, out result); }
/// <summary> /// Should the given method be excluded from an sign converted overload? /// </summary> private static bool AvoidConvertSignedBytes(MethodDefinition javaMethod) { var className = javaMethod.DeclaringClass.ClassName; switch (className) { case "java/nio/ByteBuffer": return (javaMethod.Name == "array"); case "java/lang/Byte": case "java/lang/Short": case "java/lang/Integer": case "java/lang/Long": case "java/lang/Float": case "java/lang/Double": case "java/lang/Number": return true; } if (javaMethod.DeclaringClass.IsInterface) return true; return false; }
protected override bool ShouldImplement(MethodDefinition method, TargetFramework target) { if (method.Name == "clone") return false; return base.ShouldImplement(method, target); }
/// <summary> /// Mark all eachable items in argument as such. /// </summary> private static void Walk(ReachableContext context, MethodDefinition method) { method.DeclaringClass.MarkReachable(context); method.ReturnType.MarkReachable(context); // All parameters foreach (var param in method.Parameters) { param.MarkReachable(context); } // Base methods if (!method.IsStatic && !method.IsFinal) { MethodDefinition baseMethod; if ((baseMethod = method.GetBaseMethod()) != null) { if (context.Contains(baseMethod.DeclaringClass)) { baseMethod.MarkReachable(context); } } } Walk(context, method.Body); }
/// <summary> /// Update the attributes of the given method /// </summary> public override MethodAttributes GetMethodAttributes(MethodDefinition method, MethodAttributes attributes) { return GetMethodAttributes(typeDef, method, attributes); }
/// <summary> /// Should the given method be implemented? /// </summary> protected override bool ShouldImplement(MethodDefinition method, TargetFramework target) { return base.ShouldImplement(method, target) && (method.Name != "<init>"); }