/// <summary> /// Gets the field attributes. /// </summary> /// <param name="jf">The java field.</param> /// <returns>The attributes of the field.</returns> public static FieldAttributes GetAttributes(this JavaField jf) { Guard.NotNull(ref jf, nameof(jf)); JavaFieldAccessFlags accessFlags = jf.AccessFlags; FieldAttributes result = 0; if (accessFlags.HasFlag(JavaFieldAccessFlags.Static)) { result |= FieldAttributes.Static; } if (accessFlags.HasFlag(JavaFieldAccessFlags.Public)) { result |= FieldAttributes.Public; } if (accessFlags.HasFlag(JavaFieldAccessFlags.Private)) { result |= FieldAttributes.Private; } if (accessFlags.HasFlag(JavaFieldAccessFlags.Protected)) { result |= FieldAttributes.Family; } return(result); }
public static MetadataJavaField ToMetadata(this JavaField field) { var javaField = new MetadataJavaField { Name = field.Name, Type = field.Type.GetSignature() }; if (field.ConstantValue != null) { using var stream = new MemoryStream(); using var ms = new MemoryOutputStream(stream); using var dos = new DataOutputStream(ms); field.ConstantValue.Dump(dos); //Write the original string there to be able to create a new constantpool from metadata if (field.ConstantValue is ConstantString constantString) { dos.WriteUTF(constantString.GetBytes(field.ConstantPool)); } javaField.ConstantValue = stream.ToArray(); } return(javaField); }
/// <summary> /// Gets the descriptor of a method. /// </summary> /// <param name="jf">The java field.</param> /// <param name="jc">The java class.</param> /// <returns>The descriptor of the java method.</returns> public static string GetDescriptor(this JavaField jf, JavaClass jc) { Guard.NotNull(ref jc, nameof(jc)); Guard.NotNull(ref jf, nameof(jf)); return(jc.GetConstant <JavaConstantUtf8>(jf.DescriptorIndex).Value); }
public void AddItemsToCart() { JavaField.SendKeys("1" + Keys.Enter); RubyField.SendKeys("2"); PythonField.SendKeys("1"); AddButton.Click(); }
void LoadDll(string file, string sourceIdentifier = null) { foreach (var ta in AssemblyDefinition.ReadAssembly(file).Modules.SelectMany(m => m.Types.SelectMany(t => FlattenTypeHierarchy(t))) .Where(ta => !ta.Name.EndsWith("Invoker", StringComparison.Ordinal) && !ta.Name.EndsWith("Implementor", StringComparison.Ordinal)) .Select(t => new Tuple <TypeDefinition, CustomAttribute> (t, GetRegisteredAttribute(t))) .Where(p => p.Item2 != null)) { var td = ta.Item1; var tatt = PopulateRegisterAttributeInfo(ta.Item2, true); var pkg = Api.Packages.FirstOrDefault(p => p.Name == tatt.Package); if (pkg == null) { Api.Packages.Add(pkg = new JavaPackage(Api) { Name = tatt.Package }); } var type = td.IsInterface ? (JavaType) new JavaInterface(pkg) : new JavaClass(pkg); type.Name = tatt.Name; type.SetExtension(td); pkg.Types.Add(type); foreach (var fa in td.Fields .Select(f => new Tuple <FieldDefinition, CustomAttribute> (f, GetRegisteredAttribute(f))) .Where(p => p.Item2 != null)) { var matt = PopulateRegisterAttributeInfo(fa.Item2); var f = new JavaField(type) { Name = matt.Name, Static = fa.Item1.IsStatic, Final = fa.Item1.HasConstant }; f.SetExtension(fa.Item1); type.Members.Add(f); } foreach (var ma in GetAllMethods(td) .Where(m => m != null) .Select(m => new Tuple <MethodDefinition, CustomAttribute> (m, GetRegisteredAttribute(m))) .Where(p => p.Item2 != null)) { var matt = PopulateRegisterAttributeInfo(ma.Item2); var m = new JavaMethod(type) { Name = matt.Name, Abstract = ma.Item1.IsAbstract, Static = ma.Item1.IsStatic }; var jniParameters = matt.JniSignature.Substring(0, matt.JniSignature.IndexOf(')')).Substring(1); m.Return = ParseJniParameters(matt.JniSignature.Substring(matt.JniSignature.IndexOf(')') + 1)).First(); m.Parameters = ParseJniParameters(jniParameters) .Zip(ma.Item1.Parameters, (s, mp) => new { Type = s, ManagedParameter = mp }) .Select(_ => new JavaParameter(m) { Name = _.ManagedParameter.Name, Type = _.Type }) .ToArray(); m.SetExtension(ma.Item1); type.Members.Add(m); } } FillSourceIdentifier(Api, sourceIdentifier ?? file); }
private string TraverseField(JavaField javaField) { var declaredAccesibility = accessibilityResolver.ResolveAccesebility(javaField.DeclaredAccessibility); var staticStr = javaField.IsStatic ? "static" : ""; var fieldStr = string.Format("{0} {1} {2} {3}", declaredAccesibility, staticStr, javaTypeResolver.Resolve(javaField.TypeSymbol), javaField.FieldName); return(javaField.Initialization != null ? string.Format("{0} = {1}", fieldStr, statementTraverser.TraverseStmt(javaField.Initialization)).Trim() : fieldStr.Trim()); }
/// <summary> /// Reads fields from the stream. /// </summary> /// <param name="stream">The stream to read the fields from.</param> /// <param name="count">The number of fields to read.</param> /// <param name="constantPool">The constant pool used for finding the attribute names.</param> /// <returns>The fields read from the stream.</returns> private static JavaField[] ReadFields(Stream stream, int count, JavaConstantPool constantPool) { JavaField[] result = new JavaField[count]; for (int i = 0; i < count; i++) { result[i] = ReadField(stream, constantPool); } return(result); }
public JavaField ResoverField() { if (Field == null) { var targetclass = this.ResoverClass(); var temp = targetclass.LookUpField(this.Name, this.Desc); if (!temp.IsAccessTo(targetclass)) { throw new Exception(); } Field = temp; } return(Field); }
public static void ConstructorTest() { JavaFieldAccessFlags flags = JavaFieldAccessFlags.Enum | JavaFieldAccessFlags.Private; ushort us1 = 1; ushort us2 = 2; ushort us3 = 3; IJavaAttribute[] attributes = new IJavaAttribute[2]; JavaField jf = new JavaField(flags, us1, us2, us3, attributes); AssertThat(jf.AccessFlags).IsEqualTo(flags); AssertThat(jf.NameIndex).IsEqualTo(us1); AssertThat(jf.DescriptorIndex).IsEqualTo(us2); AssertThat(jf.AttributesCount).IsEqualTo(us3); AssertThat(jf.Attributes).ContainsExactly(attributes); }
public IJavaData Convert(JavaObject @object) { JavaObject transformed = new JavaObject(@object.Type); transformed.Fields.AddRange(@object.Fields); for (int i = 1; i < @object.Custom.Count; i += 2) { JavaValue value = @object.Custom[i] as JavaValue; if (value == null) { continue; } JavaField field = new JavaField(value.Get <string>(), @object.Custom[i + 1]); transformed.Fields.Add(field); } return(transformed); }
/// <summary> /// Gets the attributes of the given type. /// </summary> /// <typeparam name="T">The type of the attributes.</typeparam> /// <param name="jf">The java field.</param> /// <returns>The attributes of the given type.</returns> public static T[] GetAttributes <T>(this JavaField jf) where T : IJavaAttribute { Guard.NotNull(ref jf, nameof(jf)); List <T> result = new List <T>(); foreach (IJavaAttribute attribute in jf.Attributes) { if (attribute is T matched) { result.Add(matched); } } return(result.ToArray()); }
FieldDefinition BuildCilField(TypeDefinition cilType, JavaField jfield) { FieldAttributes attrs = 0; if ((jfield.Flags & JavaAccessFlags.ACC_PUBLIC) != 0) { attrs = FieldAttributes.Public; } else if ((jfield.Flags & JavaAccessFlags.ACC_PRIVATE) != 0) { attrs = FieldAttributes.Private; } else if ((jfield.Flags & JavaAccessFlags.ACC_PROTECTED) != 0) { attrs = FieldAttributes.FamORAssem; } else { attrs = FieldAttributes.Assembly; } if ((jfield.Flags & JavaAccessFlags.ACC_STATIC) != 0) { attrs |= FieldAttributes.Static; } if ((jfield.Flags & JavaAccessFlags.ACC_FINAL) != 0) { attrs |= FieldAttributes.InitOnly; } var fieldDef = new FieldDefinition( jfield.Name, attrs, CilTypeReference(jfield.Type)); if (cilType.IsInterface && jfield.Constant != null) { fieldDef.Constant = jfield.Constant; fieldDef.IsLiteral = true; } return(fieldDef); }
public IEnumerable <IJavaData> Select(IJavaData data) { if (data is JavaArray) { foreach (IJavaData child in ((JavaArray)data).Items) { foreach (IJavaData result in Select(child)) { yield return(result); } } } else if (data is JavaObject) { JavaField field = ((JavaObject)data).Fields.FirstOrDefault(f => f.Name == Name); if (field != null) { yield return(field.Value); } } }
public static JavaClass MakeGenericClass(JavaClass fromClass, CilType fromType) { // if the generic class has static fields or a static initializer // then we need to move those into a separate class that can be // instantiated multiple times for multiple separate instances, // one for each concrete implementation of the generic type. int numGeneric = fromType.GenericParameters.Count; var dataClass = MoveStaticFields(fromClass, null); dataClass = MoveStaticInit(fromClass, dataClass); if (dataClass != null) { FixConstructorInData(dataClass, numGeneric); } // a generic class implements the IGenericObject interface, // and has a generic-type field for the concrete implementation // of the generic type and generic arguments CreateGenericTypeFields(fromClass, numGeneric); BuildGetTypeMethod(fromClass, fromType); return(dataClass); // // move any static fields from the generic class, // as instance fields in a new class // JavaClass MoveStaticFields(JavaClass fromClass, JavaClass dataClass) { var fields = fromClass.Fields; if (fields == null) { return(dataClass); } int n = fields.Count; for (int i = 0; i < n;) { var fld = fields[i]; if ((fld.Flags & JavaAccessFlags.ACC_STATIC) == 0) { i++; continue; } if (((CilType)fld.Type).IsLiteral) { i++; continue; } if (dataClass == null) { dataClass = CreateClass(fromClass); } if (fld.Constant != null) { throw CilMain.Where.Exception($"initializer in static field '{fld.Name}' in generic class"); } fields.RemoveAt(i); n--; fld.Flags &= ~JavaAccessFlags.ACC_STATIC; dataClass.Fields.Add(fld); } return(dataClass); } // // move the static constructor/initializer // from the generic class to the new data class // JavaClass MoveStaticInit(JavaClass fromClass, JavaClass dataClass) { var methods = fromClass.Methods; int n = methods.Count; for (int i = 0; i < n;) { var mth = methods[i]; if (mth.Name != "<clinit>") { i++; continue; } if (dataClass == null) { dataClass = CreateClass(fromClass); } methods.RemoveAt(i); n--; mth.Name = "<init>"; mth.Class = dataClass; mth.Flags = JavaAccessFlags.ACC_PUBLIC; dataClass.Methods.Add(mth); } return(dataClass); } // // create a constructor if there was no static initializer, // or inject a call to super class constructor // void FixConstructorInData(JavaClass dataClass, int numGeneric) { JavaCode code; bool insertReturn; if (dataClass.Methods.Count == 0) { code = CilMethod.CreateConstructor(dataClass, numGeneric, true); insertReturn = true; code.MaxStack = 1; code.MaxLocals = 1 + numGeneric; } else { code = dataClass.Methods[0].Code; if (code.MaxStack < 1) { code.MaxStack = 1; } // we are injecting a call to super constructor at the very top, // so local 0 should have the proper type, not uninitializedThis code.StackMap.SetLocalInAllFrames( 0, CilType.From(new JavaType(0, 0, dataClass.Name)), null); insertReturn = false; } code.Instructions.Insert(0, new Instruction( 0x19 /* aload */, null, (int)0, 0xFFFF)); code.Instructions.Insert(1, new Instruction( 0xB7 /* invokespecial */, JavaType.ObjectType, new JavaMethodRef("<init>", JavaType.VoidType), 0xFFFF)); // the static initializer can call static methods on its own type, // and those methods can invoke system.RuntimeType.GetType() to get // a reference to the generic type that is still being initialized. // and more importantly, a reference to the the static-generic data // object that is constructed by this method. to make the object // available to such access, we call system.RuntimeType.SetStatic(). // see also system.RuntimeType.MakeGenericType/MakeGenericType(). code.Instructions.Insert(2, new Instruction( 0x19 /* aload */, null, (int)0, 0xFFFF)); code.Instructions.Insert(3, new Instruction( 0xB8 /* invokestatic */, CilType.SystemRuntimeTypeType, new JavaMethodRef("SetStatic", JavaType.VoidType, JavaType.ObjectType), 0xFFFF)); if (insertReturn) { code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null, 0xFFFF); } } // // create the new data class // JavaClass CreateClass(JavaClass fromClass) => CilMain.CreateInnerClass(fromClass, fromClass.Name + "$$static", 0, markGenericEntity: true); // // create a private instance field to hold the runtime type // for a particular combination of generic type and arguments // void CreateGenericTypeFields(JavaClass fromClass, int numGeneric) { var fld = new JavaField(); fld.Name = ConcreteTypeField.Name; fld.Type = ConcreteTypeField.Type; fld.Class = fromClass; fld.Flags = JavaAccessFlags.ACC_PRIVATE; if (fromClass.Fields == null) { fromClass.Fields = new List <JavaField>(); } fromClass.Fields.Add(fld); } }
// // // public static void CreateGenericVarianceField(JavaClass theClass, CilType fromType, TypeDefinition defType) { // check if any of the generic parameters are variant. // note that generic parameter variance is only supported // on interfaces and delegates. if (!(fromType.IsInterface || fromType.IsDelegate)) { return; } string varianceString = null; bool anyVariance = false; foreach (var gp in defType.GenericParameters) { if ((gp.Attributes & GenericParameterAttributes.VarianceMask) != 0) { anyVariance = true; break; } } if (!anyVariance) { /* removed; see IComparer.cs in baselib * if (fromType.JavaName == "system.collections.generic.IComparer$$1") * { * // force a variance string for an interface that we create * // as an abstract class; see also IComparer.cs in baselib * varianceString = "I"; * } * else*/ return; } // build a string that describes the generic variance if (varianceString == null) { var chars = new char[defType.GenericParameters.Count]; int idx = 0; foreach (var gp in defType.GenericParameters) { var v = gp.Attributes & GenericParameterAttributes.VarianceMask; chars[idx++] = (v == GenericParameterAttributes.Covariant) ? 'O' : (v == GenericParameterAttributes.Contravariant) ? 'I' : ' '; } varianceString = new string(chars); } var varianceField = new JavaField(); varianceField.Name = "-generic-variance"; varianceField.Type = JavaType.StringType; varianceField.Flags = JavaAccessFlags.ACC_STATIC | JavaAccessFlags.ACC_FINAL | JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_TRANSIENT | JavaAccessFlags.ACC_SYNTHETIC; varianceField.Constant = varianceString; varianceField.Class = theClass; if (theClass.Fields == null) { theClass.Fields = new List <JavaField>(); } theClass.Fields.Add(varianceField); }
public static List <JavaClass> BuildProxyMethods(List <CilInterface> allInterfaces, TypeDefinition fromType, CilType intoType, JavaClass theClass) { // // process only if the class (or interface) has any methods or super interfaces // var classMethods = theClass.Methods; if (classMethods.Count == 0) { return(null); } bool isInterface = intoType.IsInterface; if ((!isInterface) && theClass.Interfaces == null) { return(null); } var theMethods = CilInterfaceMethod.CollectAll(fromType); // // if any interfaces are marked [RetainName], make sure that // all corresponding methods are also marked [RetainName] // CheckRetainNameMethods(theMethods, allInterfaces, intoType); // // if this is an abstract class but forced to an interface via [AddInterface] // decoration, then we need to remove all constructors generated for the class // if (intoType.IsInterface) { if (!fromType.IsInterface) { for (int i = classMethods.Count; i-- > 0;) { if (classMethods[i].Name == "<init>") { classMethods.RemoveAt(i); } } } if (intoType.HasGenericParameters) { // the RuntimeType constructor in baselib uses IGenericEntity // marker interface to identify generic classes. note that // real generic types implement IGenericObject -> IGenericEntity. theClass.AddInterface("system.IGenericEntity"); } return(null); } // // for each implemented interface, build proxy methods // List <JavaClass> output = null; int ifcNumber = 0; foreach (var ifc in allInterfaces) { if ((!ifc.DirectReference) && ifc.SuperImplements) { // we don't have to build proxy for an interface if it is // implemented by a super type and not by our primary type continue; } if (ifc.GenericTypes == null) { foreach (var ifcMethod in ifc.Methods) { // build proxy methods: interface$method -> method var newMethod = BuildPlainProxy(ifcMethod, intoType, theMethods); if (newMethod != null) { newMethod.Class = theClass; theClass.Methods.Add(newMethod); } } } else { var ifcClass = CreateInnerClass(theClass, intoType, ++ifcNumber); ifcClass.AddInterface(ifc.InterfaceType.JavaName); if (output == null) { output = new List <JavaClass>(); CreateInterfaceArrayField(theClass); } output.Add(ifcClass); // if the class implements a generic interface for multiple types, // then we need a method suffix to differentiate between the methods. // see also: CilMethod::InsertMethodNamePrefix string methodSuffix = ""; foreach (var genericType in ifc.GenericTypes) { methodSuffix += "--" + CilMethod.GenericParameterSuffixName(genericType); } foreach (var ifcMethod in ifc.Methods) { // build proxy classes: proxy sub-class -> this class BuildGenericProxy(ifcMethod, methodSuffix, intoType, theMethods, ifcClass); } } } return(output); JavaClass CreateInnerClass(JavaClass parentClass, CilType parentType, int ifcNumber) { // generic interfaces are implemented as proxy sub-classes which // call methods on the parent class object. we need to define // an inner class. this class has one instance field which is a // reference to the parent class. the constructor takes this // reference as a parameter and initializes the instance field. var newClass = CilMain.CreateInnerClass(parentClass, parentClass.Name + "$$generic" + ifcNumber.ToString()); var fld = new JavaField(); fld.Name = ParentFieldName; fld.Type = parentType; fld.Class = newClass; fld.Flags = JavaAccessFlags.ACC_PRIVATE; newClass.Fields.Add(fld); var code = CilMain.CreateHelperMethod(newClass, new JavaMethodRef("<init>", JavaType.VoidType, JavaType.ObjectType), 2, 2); code.Method.Flags &= ~JavaAccessFlags.ACC_BRIDGE; // invalid for constructor code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0xB7 /* invokespecial */, JavaType.ObjectType, new JavaMethodRef("<init>", JavaType.VoidType)); code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0x19 /* aload */, null, (int)1); code.NewInstruction(0xC0 /* checkcast */, parentType, null); code.NewInstruction(0xB5 /* putfield */, new JavaType(0, 0, newClass.Name), new JavaFieldRef(ParentFieldName, parentType)); code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null); return(newClass); } void CreateInterfaceArrayField(JavaClass parentClass) { // the parent class has a helper array field that is used to track // the proxy objects generated for implemented generic interfaces. // see also: InitInterfaceArrayField, below. var fld = new JavaField(); fld.Name = InterfaceArrayField.Name; fld.Type = InterfaceArrayField.Type; fld.Class = parentClass; fld.Flags = JavaAccessFlags.ACC_PRIVATE; if (parentClass.Fields == null) { parentClass.Fields = new List <JavaField>(1); } parentClass.Fields.Add(fld); } }
public static void ImportFields(JavaClass jclass, TypeDefinition cilType, bool isRetainName) { if (cilType.HasFields) { int n = cilType.Fields.Count; if (n > 0) { if (isRetainName) { throw CilMain.Where.Exception("fields not supported in a [RetainName] type"); } jclass.Fields = new List <JavaField>(n); for (int i = 0; i < n; i++) { var cilField = cilType.Fields[i]; CilMain.Where.Push($"field '{cilField.Name}'"); if (cilField.InitialValue.Length != 0) { throw CilMain.Where.Exception("unsupported InitialValue in field"); } var myField = new JavaField(); myField.Name = CilMain.MakeValidMemberName(cilField.Name); myField.Class = jclass; myField.Flags = AttributesToAccessFlags( cilField.Attributes, (cilType.HasNestedTypes || cilType.HasGenericParameters)); if (cilType.IsEnum) { myField.Type = CilType.From(cilField.FieldType); if (cilField.Constant != null) { myField.InitConstant(cilField.Constant, CilMain.Where); } } else { myField.Type = ValueUtil.GetBoxedFieldType(null, cilField); if (((CilType)myField.Type).IsValueClass) { myField.Constant = cilField; } else { if (cilField.Constant != null) { myField.InitConstant(cilField.Constant, CilMain.Where); } if (((CilType)myField.Type).IsVolatile) { myField.Flags |= JavaAccessFlags.ACC_VOLATILE; } } } jclass.Fields.Add(myField); CilMain.Where.Pop(); } } } }
IEnumerable <ApiComparisonReport> CompareField(JavaField rf, JavaField tf) { // return CompareProperty (nameof (rf.Deprecated), rf, tf, _ => _.Deprecated); return(CompareProperty(nameof(rf.Final), rf, tf, _ => _.Final)); }
IEnumerable <ApiComparisonReport> CompareProperty <T> (string propertyName, JavaField rf, JavaField tf, Func <JavaField, T> getProperty) { return(CompareProperty(propertyName, rf, tf, getProperty, _ => _.Parent.FullName + "." + _.Name, ApiComparisonIssue.FieldPropertyMismatch)); }
private static FieldDefinition ConvertField(AssemblyDefinition assembly, JavaClass jc, JavaField jf) { string name = jf.GetName(jc); FieldAttributes attributes = jf.GetAttributes(); FieldDefinition result = new FieldDefinition(name, attributes, assembly.MainModule.GetDescriptorType(jf.GetDescriptor(jc))); return(result); }
/// <summary> /// Gets the attribute of the given type. /// </summary> /// <typeparam name="T">The type of the attribute.</typeparam> /// <param name="jf">The java field.</param> /// <returns>The attribute of the given type.</returns> public static T GetAttribute <T>(this JavaField jf) where T : IJavaAttribute { Guard.NotNull(ref jf, nameof(jf)); return(jf.GetAttributes <T>().FirstOrDefault()); }
internal static void BuildJavaClass(TypeDefinition cilType, JavaClass parentClass) { CilMain.Where.Push($"class '{cilType.FullName}'"); var genericMark = CilMain.GenericStack.Mark(); var myType = CilMain.GenericStack.EnterType(cilType); var jclass = new JavaClass(); jclass.Name = myType.JavaName; jclass.Flags = AttributesToAccessFlags(cilType.Attributes, myType.IsInterface); if (myType.IsInterface) { jclass.Super = JavaType.ObjectType.ClassName; // java.lang.Object } else if (cilType.BaseType != null) { var myBaseType = CilType.From(cilType.BaseType); jclass.Super = myBaseType.Equals(JavaType.ObjectType) ? JavaType.ObjectType.ClassName // java.lang.Object : myBaseType.JavaName; } else { throw CilMain.Where.Exception("missing base class"); } var myInterfaces = ImportInterfaces(jclass, myType, cilType); int numCastableInterfaces = myType.IsGenericThisOrSuper ? InterfaceBuilder.CastableInterfaceCount(myInterfaces) : 0; ImportFields(jclass, cilType, myType.IsRetainName); ImportMethods(jclass, cilType, numCastableInterfaces); if (myType.JavaName == "system.Convert") { DiscardBase64MethodsInConvertClass(jclass); } ValueUtil.InitializeStaticFields(jclass, myType); if (myType.IsValueClass) { ValueUtil.MakeValueClass(jclass, myType, numCastableInterfaces); } else if (myType.IsEnum) { ValueUtil.MakeEnumClass(jclass, myType, cilType.HasCustomAttribute("System.FlagsAttribute", true)); } else if (myType.IsDelegate) { var delegateInterface = Delegate.FixClass(jclass, myType); CilMain.JavaClasses.Add(delegateInterface); } // if derives directly from object, and does not implement ToString CodeBuilder.CreateToStringMethod(jclass); ResetFieldReferences(jclass); LinkClasses(jclass, parentClass, cilType); var interfaceClasses = InterfaceBuilder.BuildProxyMethods( myInterfaces, cilType, myType, jclass); if (interfaceClasses != null) { foreach (var childClass in interfaceClasses) { CilMain.JavaClasses.Add(childClass); } } if (myType.HasGenericParameters) { JavaClass dataClass; if (!myType.IsInterface) { dataClass = GenericUtil.MakeGenericClass(jclass, myType); if (dataClass != null) { CilMain.JavaClasses.Add(dataClass); } } else { dataClass = null; } JavaClass infoClass = jclass; if (myType.IsInterface) { // Android 'D8' desugars static methods on an interface by // moving into a separate class, so we do it ourselves. // see also system.RuntimeType.CreateGeneric() in baselib infoClass = CilMain.CreateInnerClass(jclass, jclass.Name + "$$info", markGenericEntity: true); CilMain.JavaClasses.Add(infoClass); // Android 'R8' (ProGuard) might discard this new class, // so insert a dummy field with the type of the class. // see also ProGuard rules in IGenericEntity in baselib var infoClassField = new JavaField(); infoClassField.Name = "-generic-info-class"; infoClassField.Type = new JavaType(0, 0, infoClass.Name); infoClassField.Class = jclass; infoClassField.Flags = JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_STATIC | JavaAccessFlags.ACC_FINAL | JavaAccessFlags.ACC_SYNTHETIC; if (jclass.Fields == null) { jclass.Fields = new List <JavaField>(1); } jclass.Fields.Add(infoClassField); } GenericUtil.CreateGenericInfoMethod(infoClass, dataClass, myType); GenericUtil.CreateGenericVarianceField(infoClass, myType, cilType); } if (myType.IsGenericThisOrSuper) { jclass.Signature = GenericUtil.MakeGenericSignature(cilType, jclass.Super); if (!myInterfaces.Exists(x => x.InterfaceType.JavaName == "system.IGenericObject")) { if (!myType.IsInterface) { // create IGenericObject methods GetType and TryCast // only if class did not already implement IGenericObject if (!myType.HasGenericParameters) { GenericUtil.BuildGetTypeMethod(jclass, myType); } InterfaceBuilder.BuildTryCastMethod( myInterfaces, myType, numCastableInterfaces, jclass); } } } CilMain.GenericStack.Release(genericMark); CilMain.Where.Pop(); }
public static void CreateSuppressibleFinalize(JavaMethod innerMethod, CilType declType, JavaClass theClass) { // // if the class defines a finalizer method Finalize() then: // // - create a flag field that tracks whether finalization is suppressed // // - implement interface system.GC.FinalizeSuppressible, and its Set() // method, which sets the flag field // // - create a wrapper method that checks the flag field and possibly // invokes the original finalizer // // see also: system.GC in baselib // var flagField = new JavaField(); flagField.Name = "-finalize-suppressed"; flagField.Type = CilType.From(JavaType.BooleanType); flagField.Class = theClass; flagField.Flags = JavaAccessFlags.ACC_PRIVATE | JavaAccessFlags.ACC_VOLATILE; if (theClass.Fields == null) { theClass.Fields = new List <JavaField>(); } theClass.Fields.Add(flagField); // // implement the interface method // var ifcMethod = new JavaMethod("system-GC$SuppressibleFinalize-Set", JavaType.VoidType); ifcMethod.Class = theClass; ifcMethod.Flags = JavaAccessFlags.ACC_PUBLIC; var code = ifcMethod.Code = new JavaCode(); code.Method = ifcMethod; code.Instructions = new List <JavaCode.Instruction>(); code.MaxLocals = code.MaxStack = 2; code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0x12 /* ldc */, null, (int)1); code.NewInstruction(0xB5 /* putfield */, declType, flagField); code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null); theClass.Methods.Add(ifcMethod); theClass.AddInterface("system.GC$SuppressibleFinalize"); // // create the wrapper method // var outerMethod = new JavaMethod(theClass, innerMethod); outerMethod.Flags = JavaAccessFlags.ACC_PROTECTED; innerMethod.Flags = JavaAccessFlags.ACC_PRIVATE; innerMethod.Name += "---inner"; // prepare to generate instructions code = outerMethod.Code = new JavaCode(); code.Method = outerMethod; code.Instructions = new List <JavaCode.Instruction>(); code.StackMap = new JavaStackMap(); code.StackMap.SaveFrame((ushort)0, false, CilMain.Where); code.MaxLocals = code.MaxStack = 1; // // check the flag field to determine if suppressed // code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, declType, flagField); code.NewInstruction(0x9A /* ifne != zero */, null, (ushort)0xFFFE); code.NewInstruction(0x19 /* aload */, null, (int)0); code.NewInstruction(0xB7 /* invokespecial */, declType, innerMethod); code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null, /* label */ 0xFFFE); code.StackMap.SaveFrame((ushort)0xFFFE, true, CilMain.Where); theClass.Methods.Add(outerMethod); }
public void clearFields() { JavaField.Clear(); RubyField.Clear(); PythonField.Clear(); }