public JavaField(JavaClass owningClass, string declaration) : base(owningClass) { Declaration = declaration; if (declaration.IndexOf('=') != -1) // Declaration has an assignment, cut it off. declaration = declaration.Remove(declaration.IndexOf('=') - 1); string[] tokens = declaration.Split(' '); Name = tokens[tokens.Length - 2]; Type = owningClass.ResolveConstants(tokens[tokens.Length - 1]); //if (ShouldRename(name)) //{ // string newFieldName = "origField" + fieldNameMap.Count; // string fullFieldName = fullClassName + " " + name + " " + type; // string newFullName = fullClassName + " " + newFieldName + " " + type; // string newDeclaration = ReplaceFirst(fieldLine, name, newFieldName); // fieldNameMap.Add(new JavaMember(file, fieldLine, fullFieldName), new JavaMember(file, newDeclaration, newFullName)); // Console.WriteLine(newFieldName + " <- " + fullFieldName); // logger.WriteLine(newFieldName + ": " + fullFieldName); //} }
/// <summary> /// Constructor. /// </summary> public JavaClassProperty(string name, string javaType, bool isCollection, JavaClass javaClass) { Name = name; JavaType = javaType; IsCollection = isCollection; JavaClass = javaClass; }
/// <summary> /// Default ctor /// </summary> internal AssemblyClasses(AssemblyDefinition assembly, Action<ClassSource> jarLoaded=null) { this.assembly = assembly; foreach (var attr in assembly.GetJavaCodeAttributes()) { var resourceName = (string)attr.ConstructorArguments[0].Value; var fileName = attr.ConstructorArguments.Count > 1 ? (string)attr.ConstructorArguments[1].Value : null; JavaCode javaCode; if (!javaCodes.TryGetValue(resourceName, out javaCode)) { var resource = assembly.MainModule.Resources.FirstOrDefault(x => x.Name == resourceName) as EmbeddedResource; if (resource == null) throw new LoaderException("Cannot find resource " + resourceName); javaCode = new JavaCode(resource, fileName); javaCodes[resourceName] = javaCode; if (jarLoaded != null) jarLoaded(javaCode.ClassSource); foreach (var classFileName in javaCode.Resolve(null).ClassFileNames) { var className = classFileName; if (className.EndsWith(".class", StringComparison.OrdinalIgnoreCase)) { className = className.Substring(0, className.Length - ".class".Length); } var jClass = new JavaClass(className, javaCode); javaClasses[className] = jClass; } } } var scope = AssemblyResolver.IsFrameworkAssembly(assembly) ? AttributeConstants.Dot42Scope : assembly.FullName; var ignoreFromJavaTypes = new List<TypeDefinition>(); foreach (var type in assembly.MainModule.Types) { CollectDexImportClasses(type, className2DexImportMap, type2DexImportMap, null, scope, ignoreFromJavaTypes); } foreach (var type in ignoreFromJavaTypes) { var attr = type.GetDexOrJavaImportAttribute(); var className = (string)attr.ConstructorArguments[0].Value; DexImport dexImport; if (className2DexImportMap.TryGetValue(className, out dexImport)) { dexImport.AddType(type); type2DexImportMap[type] = dexImport; } } }
public bool TryGetClass(GetMemberBinder binder, out object result) { string qualifiedName = GetQualifiedName(binder.Name); // Try to find the class with this name and fail if not found. I really tried to find anyway // in java to check for class existence without exceptions but couldn't find any. try { IntPtr classPtr = _vm.FindClass(qualifiedName); result = new JavaClass(_vm, classPtr, IntPtr.Zero, qualifiedName); return true; } catch (JavaException) { result = null; return false; } }
/// <summary> /// Gets a java class by it's classname. /// </summary> /// <returns>False if not found.</returns> internal bool TryGetJavaClass(string className, out JavaClass jClass) { return(javaClasses.TryGetValue(className, out jClass)); }
/// <summary> /// Gets the constant from the constant pool. /// </summary> /// <typeparam name="T">The type of the constant.</typeparam> /// <param name="jc">The java class.</param> /// <param name="index">The index of the constant in the constant pool.</param> /// <returns>The java constant.</returns> public static T GetConstant <T>(this JavaClass jc, ushort index) where T : IJavaConstant { Guard.NotNull(ref jc, nameof(jc)); return((T)jc.ConstantPool[index]); }
// // // 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 void BuildOverloadProxy(TypeDefinition fromType, MethodDefinition fromMethod, CilMethod targetMethod, JavaClass intoClass) { // create a proxy bridge to forward invocations of a virtual method from // the base class, to an implementation in a derived class. this is needed // where the base virtual method has generic parameters or return type, // for example: virtual T SomeMethod(T arg) will be translated as: // java.lang.Object SomeMethod(-generic-$)(java.lang.Object arg) // and in a derived class that specializes T as String: // java.lang.String SomeMethod(java.lang.String arg) // so the derived class must also include a proxy bridge method with the // same name as in the base class, and forward the call. //Console.WriteLine($"CHECK OVERRIDE {fromMethod}"); int targetMethodCount = targetMethod.Parameters.Count; for (;;) { var baseType = fromType.BaseType; if (baseType == null) { break; } fromType = CilType.AsDefinition(baseType); if (!baseType.IsGenericInstance) { continue; } foreach (var fromMethod2 in fromType.Methods) { //Console.WriteLine($"\tCOMPARE {fromMethod2} {fromMethod2.IsVirtual} {fromMethod2.Name == fromMethod.Name} {targetMethodCount == fromMethod2.Parameters.Count}"); if (fromMethod2.IsVirtual && fromMethod2.Name == fromMethod.Name && targetMethodCount == fromMethod2.Parameters.Count) { if (CilMethod.CompareMethods(fromMethod, fromMethod2)) { //Console.WriteLine(">>>>>>>>>>>>> WARNING SAME: " + fromMethod.ToString() + " AND " + fromType); continue; } var genericMark = CilMain.GenericStack.Mark(); CilMain.GenericStack.EnterType(baseType); var baseMethod = new CilInterfaceMethod( CilMain.GenericStack.EnterMethod(fromMethod2)); CilMain.GenericStack.Release(genericMark); //Console.WriteLine($"\twould compare with {fromMethod2} in class {baseType}"); //Console.WriteLine($"\t\t{baseMethod}"); if (targetMethodCount != baseMethod.Parameters.Count) { continue; } if (!IsGenericOrEqual(targetMethod.ReturnType, baseMethod.ReturnType)) { continue; } bool sameParameters = true; for (int i = 0; i < targetMethodCount; i++) { if (!IsGenericOrEqual(targetMethod.Parameters[i].Type, baseMethod.Parameters[i])) { bool equalsAfterUnboxing = ( targetMethod.Parameters[i].Type is BoxedType boxedType && boxedType.UnboxedType.Equals(baseMethod.Parameters[i])); if (!equalsAfterUnboxing) { //Console.WriteLine($"\tMISMATCH {targetMethod.Parameters[i].Type} vs {baseMethod.Parameters[i]}/{baseMethod.Parameters[i].IsGenericParameter}"); sameParameters = false; break; } } } if (sameParameters) { //Console.WriteLine($"proxying {targetMethod} in class {targetMethod.DeclType}"); BuildGenericProxy2(baseMethod, targetMethod, false, targetMethod.DeclType, intoClass); return; } } } }
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(); } } } }
public void TestJavaClass(ByteOrder order) { var javaEnum = new JavaClass(TestSupport.RandomString()); AssertSerialization(javaEnum, order); }
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 JavaClass FixClass(JavaClass fromClass, CilType fromType) { JavaType interfaceType = InterfaceType(fromType); JavaClass interfaceClass = null; foreach (var method in fromClass.Methods) { if ((method.Flags & JavaAccessFlags.ACC_STATIC) == 0 && method.Code == null) { if (method.Name == "<init>") { GenerateConstructor(method, fromType); } else if (method.Name == "Invoke") { if (interfaceClass != null) { break; } interfaceClass = MakeInterface(fromClass, method, interfaceType.ClassName); GenerateInvoke(method, fromType, interfaceType); } else if (method.Name == "BeginInvoke") { if (interfaceClass == null) { break; } GenerateBeginInvoke(); continue; } else if (method.Name == "EndInvoke") { GenerateEndInvoke(); continue; } else { break; } method.Flags &= ~JavaAccessFlags.ACC_ABSTRACT; } } if (interfaceClass == null) { throw CilMain.Where.Exception("invalid delegate class"); } return(interfaceClass); // // // JavaClass MakeInterface(JavaClass fromClass, JavaMethod fromMethod, string newName) { var newClass = CilMain.CreateInnerClass(fromClass, newName, JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_ABSTRACT | JavaAccessFlags.ACC_INTERFACE); var newMethod = new JavaMethod(newClass, fromMethod); newMethod.Flags = JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_ABSTRACT; if (IsPrimitive(newMethod.ReturnType)) { // primitive return value is translated to java.lang.Object, // because the delegate target may return a generic type that // is specialized for the primitive type in the delegate. // see also GenerateInvoke and LoadFunction newMethod.ReturnType = JavaType.ObjectType; } newClass.Methods.Add(newMethod); return(newClass); } // // // void GenerateConstructor(JavaMethod method, CilType dlgType) { var code = method.Code = new JavaCode(); code.Method = method; code.Instructions = new List <Instruction>(); if (dlgType.HasGenericParameters) { code.StackMap = new JavaStackMap(); var genericMark = CilMain.GenericStack.Mark(); CilMain.GenericStack.EnterMethod(dlgType, method, true); // initialize the generic type field GenericUtil.InitializeTypeField(dlgType, code); CilMain.GenericStack.Release(genericMark); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); } code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0x19 /* aload_1 */, null, (int)1); code.NewInstruction(0x19 /* aload_2 */, null, (int)2); code.NewInstruction(0xB7 /* invokespecial */, new JavaType(0, 0, method.Class.Super), new JavaMethodRef("<init>", JavaType.VoidType, JavaType.ObjectType, JavaType.ObjectType)); code.NewInstruction(0xB1 /* return (void) */, null, null); if (code.MaxStack < 3) { code.MaxStack = 3; } code.MaxLocals = 3 + dlgType.GenericParametersCount; } // // // void GenerateInvoke(JavaMethod method, CilType dlgType, JavaType ifcType) { var code = method.Code = new JavaCode(); code.Method = method; code.Instructions = new List <Instruction>(); code.StackMap = new JavaStackMap(); code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, new JavaType(0, 0, "system.Delegate"), new JavaFieldRef("invokable", JavaType.ObjectType)); code.NewInstruction(0xC0 /* checkcast */, ifcType, null); code.StackMap.PushStack(JavaType.ObjectType); int index = 1; for (int i = 0; i < method.Parameters.Count; i++) { var paramType = (CilType)method.Parameters[i].Type; code.NewInstruction(paramType.LoadOpcode, null, index); code.StackMap.PushStack(paramType); if (paramType.IsGenericParameter && (!paramType.IsByReference)) { // invoke the helper method which identifies our boxed // primitives and re-boxes them as java boxed values. // see also: GenericType::DelegateParameterin baselib. GenericUtil.LoadMaybeGeneric( paramType.GetMethodGenericParameter(), code); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, DelegateParameterMethod); code.StackMap.PopStack(CilMain.Where); } index += paramType.Category; } var returnType = (CilType)method.ReturnType; if (IsPrimitive(returnType)) { // primitive return value is translated to java.lang.Object, // because the delegate target may return a generic type that // is specialized for the primitive type in the delegate. // see also GenerateInvoke and LoadFunction var adjustedMethod = new JavaMethodRef( method.Name, JavaType.ObjectType, method.Parameters); code.NewInstruction(0xB9 /* invokeinterface */, ifcType, adjustedMethod); } else { code.NewInstruction(0xB9 /* invokeinterface */, ifcType, method); } code.StackMap.ClearStack(); code.StackMap.PushStack(returnType); if (returnType.IsGenericParameter && (!returnType.IsByReference)) { GenericUtil.LoadMaybeGeneric( returnType.GetMethodGenericParameter(), code); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, DelegateReturnValueMethod); code.StackMap.PopStack(CilMain.Where); } else if (IsPrimitive(returnType)) { // if the delegate returns a primitive type, we need to unbox // the object returned by the method we just called. it will be // a java boxed primitive (e.g. java.lang.Integer) if the called // method actually returns a primitive, due to the boxing done // by the invokedynamic mechanism. if the called method returns // a generic type, it will be our boxed type, e.g. system.Int32. // // see also DelegateReturnValueX helper methods in baselib, // and MakeInterface and LoadFunction in this file. var helperMethod = new JavaMethodRef( DelegateReturnValueMethod.Name + returnType.ToDescriptor(), returnType, JavaType.ObjectType); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, helperMethod); } code.NewInstruction(returnType.ReturnOpcode, null, index); code.StackMap.PopStack(CilMain.Where); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); code.MaxLocals = index; } // // // void GenerateBeginInvoke() { } // // // void GenerateEndInvoke() { } }
public JavaDaoConfig(JavaClass javaClass) { this.JavaClass = javaClass; }
/// <summary> /// Adds a java class to the conversion. /// </summary> /// <param name="jc">The java class to include.</param> public void Include(JavaClass jc) { classes.Add(jc); }
/// <summary> /// Gets the type definition from a module from a java class and constant pool index. /// </summary> /// <param name="module">The module.</param> /// <param name="jc">The java class.</param> /// <param name="classIndex">Index of the class.</param> /// <returns>The type reference.</returns> public static TypeDefinition GetJavaTypeDefinition(this ModuleDefinition module, JavaClass jc, ushort classIndex) { Guard.NotNull(ref module, nameof(module)); Guard.NotNull(ref jc, nameof(jc)); Guard.NotNull(ref classIndex, nameof(classIndex)); return(module.GetJavaType(jc, classIndex).Resolve()); }
public void Initialize() { m_liveSessionListeners = new HashSet <object>(); IStepTracker stepTracker = null; #if IOS_NATIVE if (Application.isMobilePlatform) { m_logger.Debug("Initializing iOS Native"); m_categoryOptions = IOSAudioSessionCategoryOptions.None; if (MixWithOthers) { m_categoryOptions = IOSAudioSessionCategoryOptions.MixWithOthers; } m_currentCategory = DefaultAudioCategory; if (EnableBackgroundAudio) { IOSAudioSession.Instance.SetCategory(m_currentCategory, m_categoryOptions); IOSAudioSession.Instance.RemoteCommandReceived += (sender, args) => { if (args.Command == IOSAudioRemoteCommand.Pause) { SuspendLiveSession(); } }; } if (UseNativeDownloader) { FileDownloader.SetFactory(new IOSFileDownloaderFactory()); } AppDataPath = IOSFileDownloader.AppDataPath; Accelerometer = IOSMotionManager.Instance.GetAccelerometer(); LocationManager = IOSLocationManager.Instance; SystemCompass = new IOSCompass(); if (EnableBeacons) { BeaconManager = IOSBeaconManager.Instance; } if (EnableNotifications) { LocalNotificationManager = new IOSLocalNotificationManager(IOSLocalNotificationTypes.Badge | IOSLocalNotificationTypes.Sound); } } #endif #if ANDROID_NATIVE if (Application.isMobilePlatform) { m_logger.Debug("Initializing Android Native"); JavaClass activityClass = new JavaClass("com.unity3d.player.UnityPlayer"); JavaObject mainActivity = activityClass.GetStaticFieldValue <JavaObject>("currentActivity", "android.app.Activity"); AndroidApplicationManager.Instance.Initialize(mainActivity); LocationManager = new AndroidLocationManager(); if (EnableBeacons) { BeaconManager = new AndroidBeaconManager(); } if (EnableNotifications) { LocalNotificationManager = new AndroidLocalNotificationManager(StorageManager.GetFilePath("platform", "androidNotificationManager.json")); } } #endif if (BeaconManager == null && EnableBeacons) { BeaconManager = UnityBeaconManager.Instance; } if (Accelerometer == null) { Accelerometer = gameObject.AddComponent <UnityAccelerometer>(); } if (LocationManager == null) { LocationManager = gameObject.AddComponent <UnityLocationManager>(); } LocationManager.EnableBackgroundUpdates = EnableBackgroundLocation; if (SystemCompass == null) { SystemCompass = gameObject.AddComponent <UnityCompass>(); } if (LocalNotificationManager == null) { LocalNotificationManager = new DummyLocalNotificationManager(); } if (EnableNotifications && EnableBackgroundNotifications) { BackgroundNotifier.Instance.Initialize(); } var nrCompass = new NoiseDampeningCompass(SystemCompass); #if UNITY_ANDROID // Android compass tends to be much more jittery--apply a higher dampening // factor nrCompass.DampeningFactor = 0.25; #endif NoiseReducedCompass = nrCompass; if (Application.isMobilePlatform) { var accTracker = new AccelerometerStepTracker(Accelerometer); stepTracker = accTracker; Accelerometer.Start(); accTracker.Start(); } else { stepTracker = gameObject.AddComponent <DebugStepTracker>(); } Pedometer = new Pedometer(stepTracker); m_logger.Debug("Setting compass type={0}", CompassType); switch (CompassType) { case CompassType.System: Compass = SystemCompass; break; case CompassType.NoiseReduced: Compass = NoiseReducedCompass; break; case CompassType.LocationTracker: LocationTrackerCompass = new Motive.AR.LocationServices.LocationTrackerCompass(); Compass = LocationTrackerCompass; break; case CompassType.Hybrid: default: var hybrid = new HybridCompass(NoiseReducedCompass); LocationTrackerCompass = hybrid.TrackerCompass; Compass = hybrid; break; } AudioChannel = CreateAudioPlayerChannel(); ForegroundAudioChannel = gameObject.AddComponent <UnityAudioPlayerChannel>(); Pedometer.Stepped += (sender, args) => { if (ScriptEngine.Instance.UserInteractionEventManager != null) { ScriptEngine.Instance.UserInteractionEventManager.AddEvent("step"); } }; if (ScreenSleepBehavior == ScreenSleepBehavior.AlwaysOn) { Screen.sleepTimeout = SleepTimeout.NeverSleep; } }
protected bool Equals(JavaClass other) { return string.Equals(Name, other.Name); }
public static JavaObjectFactory Object(JniWrapper vm, JavaClass javaClass) { return new JavaObjectFactory(o => new JValue(((JavaObject)o).Pointer), javaClass); }
public void LinkCilTypesByClass(TypeDefinition cilType, JavaClass jclass) { var superName = jclass.Super; if (superName == "java.lang.Enum") { superName = null; } if (superName != null) { if (typeMap.TryGetValue(superName, out var cilSuperTypeRef)) { if (cilType.IsInterface) { if (superName != "java.lang.Object") { cilType.Interfaces.Add( new InterfaceImplementation(cilSuperTypeRef)); } if (jclass.Name == "java.lang.AutoCloseable") { // make java.lang.AutoCloseable extend System.IDisposable, // to allow use of imported classes in "using" statement. // see also ConvertInterfaceCall in CodeCall module. var iDisposableRef = new TypeReference( "System", "IDisposable", module, module.TypeSystem.CoreLibrary); cilType.Interfaces.Add( new InterfaceImplementation(iDisposableRef)); } } else { if (jclass.Name == "java.lang.Throwable" && superName == "java.lang.Object") { cilSuperTypeRef = systemException; } cilType.BaseType = cilSuperTypeRef; } CilTypeAddUse(cilSuperTypeRef); } else { throw new JavaException($"super class '{superName}' not found", Where); } } if (jclass.Interfaces != null) { foreach (var interfaceName in jclass.Interfaces) { if (typeMap.TryGetValue(interfaceName, out var cilInterfaceTypeRef)) { if (cilInterfaceTypeRef.Resolve()?.IsInterface == true) { cilType.Interfaces.Add( new InterfaceImplementation(cilInterfaceTypeRef)); CilTypeAddUse(cilInterfaceTypeRef); } } else { throw new JavaException($"interface '{interfaceName}' not found", Where); } } } }
public void TestJavaClass(Endianness order) { var javaClass = new JavaClass(TestUtils.RandomString()); AssertSerialization(javaClass, order); }
public static void BuildGenericProxy(CilInterfaceMethod ifcMethod, /*string methodSuffix,*/ CilType intoType, List <CilInterfaceMethod> classMethods, JavaClass ifcClass) { CilMethod targetMethod = null; //Console.WriteLine("\n***** LOOKING FOR INTERFACE METHOD " + ifcMethod + " (SUFFIX " + methodSuffix + ") AKA " + ifcMethod.Method); foreach (var clsMethod in classMethods) { /*Console.WriteLine("> LOOKING AT " + (clsMethod.Method.IsExplicitImpl ? "EXPLICIT " : "") + "CLASS METHOD " + clsMethod + " AKA " + clsMethod.Method);*/ if (ifcMethod.GenericCompare(clsMethod)) { if (clsMethod.Method.IsExplicitImpl) { // a matching explicit override method is the best match, // and we can immediately stop searching targetMethod = clsMethod.Method; break; } else { // more than one method may match, if a derived type overrides // or hides a method that also exists in a base type. but the // derived (primary) type methods always come first if (targetMethod == null) { targetMethod = clsMethod.Method; } // if a second method matches, and the set of generic types // in its signature exactly matches the interface method we // are looking for, then prefer this method. when a class // implements same-name methods from multiple interfaces, // this is needed to pick the right method. // see also ResolvedGenericTypes in CilInterfaceMethod. else if (clsMethod.ResolvedGenericTypes.Length != 0 && clsMethod.ResolvedGenericTypes == ifcMethod.ResolvedGenericTypes) { targetMethod = clsMethod.Method; } } } } if (targetMethod == null) { throw CilMain.Where.Exception( $"missing method '{ifcMethod.Method}' " + $"(for interface '{ifcMethod.Method.DeclType}')"); } // Console.WriteLine("INTERFACE METHOD " + ifcMethod.Method + " TARGET " + targetMethod); BuildGenericProxy2(ifcMethod, targetMethod, true, intoType, ifcClass); }
public JavaMember(JavaClass owningClass) { OwningClass = owningClass; }
public JavaStubGrammar() { CommentTerminal single_line_comment = new CommentTerminal("SingleLineComment", "//", "\r", "\n"); CommentTerminal delimited_comment = new CommentTerminal("DelimitedComment", "/*", "*/"); NonGrammarTerminals.Add(single_line_comment); NonGrammarTerminals.Add(delimited_comment); IdentifierTerminal identifier = new IdentifierTerminal("identifier"); KeyTerm keyword_package = Keyword("package"); KeyTerm keyword_import = Keyword("import"); KeyTerm keyword_public = Keyword("public"); KeyTerm keyword_protected = Keyword("protected"); KeyTerm keyword_static = Keyword("static"); KeyTerm keyword_final = Keyword("final"); KeyTerm keyword_abstract = Keyword("abstract"); KeyTerm keyword_synchronized = Keyword("synchronized"); KeyTerm keyword_default = Keyword("default"); KeyTerm keyword_native = Keyword("native"); KeyTerm keyword_volatile = Keyword("volatile"); KeyTerm keyword_transient = Keyword("transient"); KeyTerm keyword_enum = Keyword("enum"); KeyTerm keyword_class = Keyword("class"); KeyTerm keyword_interface = Keyword("interface"); KeyTerm keyword_at_interface = Keyword("@interface"); KeyTerm keyword_extends = Keyword("extends"); KeyTerm keyword_implements = Keyword("implements"); KeyTerm keyword_throw = Keyword("throw"); KeyTerm keyword_throws = Keyword("throws"); KeyTerm keyword_null = Keyword("null"); KeyTerm keyword_super = Keyword("super"); KeyTerm keyword_true = Keyword("true"); KeyTerm keyword_false = Keyword("false"); KeyTerm keyword_new = Keyword("new"); var compile_unit = DefaultNonTerminal("compile_unit"); var opt_package_decl = DefaultNonTerminal("opt_package_declaration"); var package_decl = DefaultNonTerminal("package_declaration"); var imports = DefaultNonTerminal("imports"); var import = DefaultNonTerminal("import"); var type_decls = DefaultNonTerminal("type_decls"); var type_decl = DefaultNonTerminal("type_decl"); var enum_decl = DefaultNonTerminal("enum_decl"); var enum_body = DefaultNonTerminal("enum_body"); var class_decl = DefaultNonTerminal("class_decl"); var opt_generic_arg_decl = DefaultNonTerminal("opt_generic_arg_decl"); var opt_extends_decl = DefaultNonTerminal("opt_extends_decl"); var opt_implements_decl = DefaultNonTerminal("opt_implements_decl"); var implements_decl = DefaultNonTerminal("implements_decl"); var interface_decl = DefaultNonTerminal("interface_decl"); var iface_or_at_iface = DefaultNonTerminal("iface_or_at_iface"); var type_body = DefaultNonTerminal("type_body"); var type_members = DefaultNonTerminal("type_members"); var type_member = DefaultNonTerminal("type_member"); var nested_type_decl = DefaultNonTerminal("nested_type_decl"); var ctor_decl = DefaultNonTerminal("ctor_decl"); var method_decl = DefaultNonTerminal("method_decl"); var field_decl = DefaultNonTerminal("field_decl"); var opt_field_assignment = DefaultNonTerminal("opt_field_assignment"); var static_ctor_decl = DefaultNonTerminal("static_ctor_decl"); var enum_members_decl = DefaultNonTerminal("enum_members_decl"); var enum_member_initializers = DefaultNonTerminal("enum_member_initializers"); var enum_member_initializer = DefaultNonTerminal("enum_member_initializer"); var opt_enum_braces = DefaultNonTerminal("opt_enum_braces"); var opt_final_field_assign = DefaultNonTerminal("opt_final_field_assign"); var final_field_assign = DefaultNonTerminal("final_field_assign"); var terminate_decl_or_body = DefaultNonTerminal("terminate_decl_or_body"); var assignments = DefaultNonTerminal("assignments"); var assignment = DefaultNonTerminal("assignment"); var assign_expr = DefaultNonTerminal("assign_expr"); var rvalue_expressions = DefaultNonTerminal("rvalue_expressions"); var rvalue_expression = DefaultNonTerminal("rvalue_expression"); var array_literal = DefaultNonTerminal("array_literal"); var annotations = DefaultNonTerminal("annotations"); var annotation = DefaultNonTerminal("annotation"); var opt_annotation_args = DefaultNonTerminal("opt_annotation_args"); var annotation_value_assignments = DefaultNonTerminal("annotation_value_assignments"); var annot_assign_expr = DefaultNonTerminal("annot_assign_expr"); var modifiers_then_opt_generic_arg = DefaultNonTerminal("modifiers_then_opt_generic_arg"); var modifier_or_generic_arg = DefaultNonTerminal("modifier_or_generic_arg"); var modifiers = DefaultNonTerminal("modifiers"); var modifier = DefaultNonTerminal("modifier"); var argument_decls = DefaultNonTerminal("argument_decls"); var argument_decl = DefaultNonTerminal("argument_decl"); var comma_separated_types = DefaultNonTerminal("comma_separated_types"); var throws_decl = DefaultNonTerminal("throws_decl"); var opt_throws_decl = DefaultNonTerminal("opt_throws_decl"); var type_name = DefaultNonTerminal("type_name"); var dotted_identifier = DefaultNonTerminal("dotted_identifier"); var array_type = DefaultNonTerminal("array_type"); var vararg_type = DefaultNonTerminal("vararg_type"); var generic_type = DefaultNonTerminal("generic_type"); var generic_definition_arguments = DefaultNonTerminal("generic_definition_arguments"); var generic_definition_argument = DefaultNonTerminal("generic_definition_argument"); var generic_definition_constraints = DefaultNonTerminal("generic_definition_constraints"); var generic_definition_arguments_spec = DefaultNonTerminal("generic_definition_arguments_spec"); var generic_instance_arguments_spec = DefaultNonTerminal("generic_instance_arguments_spec"); var generic_instance_arguments = DefaultNonTerminal("generic_instance_arguments"); var generic_instance_argument = DefaultNonTerminal("generic_instance_argument"); var generic_instance_identifier_or_q = DefaultNonTerminal("generic_instance_identifier_or_q"); var generic_instance_constraints = DefaultNonTerminal("generic_instance_constraints"); var generic_instance_constraints_extends = DefaultNonTerminal("generic_instance_constraints_extends"); var generic_instance_constraints_super = DefaultNonTerminal("generic_instance_constraints_super"); var generic_instance_constraint_types = DefaultNonTerminal("generic_instance_constraint_types"); var impl_expressions = DefaultNonTerminal("impl_expressions"); var impl_expression = DefaultNonTerminal("impl_expression"); var call_super = DefaultNonTerminal("call_super"); var super_args = DefaultNonTerminal("super_args"); var default_value_expr = DefaultNonTerminal("default_value_expr"); var default_value_casted = DefaultNonTerminal("default_value_casted"); var default_value_literal = DefaultNonTerminal("default_value_literal"); var new_array = DefaultNonTerminal("new_array"); var runtime_exception = DefaultNonTerminal("runtime_exception"); var numeric_terminal = TerminalFactory.CreateCSharpNumber("numeric_value_literal"); numeric_terminal.AddPrefix("-", NumberOptions.AllowSign); numeric_terminal.AddPrefix("+", NumberOptions.AllowSign); //numeric_terminal.AddSuffix ("f"); numeric_terminal.AddSuffix("L"); var numeric_literal = DefaultNonTerminal("numeric_literal"); var string_literal = TerminalFactory.CreateCSharpString("string_literal"); var value_literal = DefaultNonTerminal("value_literal"); var identifier_wild = DefaultNonTerminal("identifier_wild"); // <construction_rules> compile_unit.Rule = opt_package_decl + imports + type_decls; opt_package_decl.Rule = package_decl | Empty; package_decl.Rule = keyword_package + dotted_identifier + ";"; imports.Rule = MakeStarRule(imports, import); import.Rule = keyword_import + dotted_identifier + ";"; type_decls.Rule = MakeStarRule(type_decls, type_decl); type_decl.Rule = class_decl | interface_decl | enum_decl; // FIXME: those modifiers_then_opt_generic_arg should be actually just modifiers... see modifiers_then_opt_generic_arg.Rule below. enum_decl.Rule = annotations + modifiers_then_opt_generic_arg + keyword_enum + identifier + opt_implements_decl + "{" + enum_body + "}"; enum_body.Rule = Empty | enum_members_decl + type_members; class_decl.Rule = annotations + modifiers_then_opt_generic_arg + keyword_class + identifier + opt_generic_arg_decl + opt_extends_decl + opt_implements_decl + type_body; interface_decl.Rule = annotations + modifiers_then_opt_generic_arg + iface_or_at_iface + identifier + opt_generic_arg_decl + opt_extends_decl + opt_implements_decl + type_body; iface_or_at_iface.Rule = keyword_interface | keyword_at_interface; opt_generic_arg_decl.Rule = Empty | "<" + generic_definition_arguments + ">"; opt_extends_decl.Rule = Empty | keyword_extends + implements_decl; // when it is used with an interface, it can be more than one... opt_implements_decl.Rule = Empty | keyword_implements + implements_decl; implements_decl.Rule = MakePlusRule(implements_decl, ToTerm(","), type_name); type_body.Rule = T("{") + type_members + T("}"); annotations.Rule = MakeStarRule(annotations, annotation); annotation.Rule = T("@") + dotted_identifier + opt_annotation_args; opt_annotation_args.Rule = Empty | T("(") + annotation_value_assignments + T(")"); annotation_value_assignments.Rule = rvalue_expression | MakeStarRule(annotation_value_assignments, ToTerm(","), annot_assign_expr); annot_assign_expr.Rule = assign_expr | T("{") + rvalue_expressions + T("}"); // HACK: I believe this is an Irony bug that adding opt_generic_arg_decl here results in shift-reduce conflict, but it's too complicated to investigate the actual issue. // As a workaround I add generic arguments as part of this "modifier" so that it can be safely added to a generic method declaration. modifiers_then_opt_generic_arg.Rule = MakeStarRule(modifiers_then_opt_generic_arg, modifier_or_generic_arg); modifiers.Rule = MakeStarRule(modifiers, modifier); modifier_or_generic_arg.Rule = modifier | generic_definition_arguments_spec; modifier.Rule = keyword_public | keyword_protected | keyword_final | keyword_abstract | keyword_synchronized | keyword_default | keyword_native | keyword_volatile | keyword_transient | keyword_static; type_members.Rule = MakeStarRule(type_members, type_member); type_member.Rule = nested_type_decl | ctor_decl | method_decl | field_decl | static_ctor_decl; nested_type_decl.Rule = type_decl; enum_members_decl.Rule = enum_member_initializers + ";"; enum_member_initializers.Rule = MakeStarRule(enum_member_initializers, ToTerm(","), enum_member_initializer); enum_member_initializer.Rule = annotations + identifier + opt_enum_braces; opt_enum_braces.Rule = Empty | "(" + ")"; static_ctor_decl.Rule = annotations + keyword_static + "{" + assignments + "}"; assignments.Rule = MakeStarRule(assignments, assignment); assignment.Rule = assign_expr + ";"; assign_expr.Rule = identifier + "=" + rvalue_expression; rvalue_expressions.Rule = MakeStarRule(rvalue_expressions, ToTerm(","), rvalue_expression); rvalue_expression.Rule = value_literal | new_array | type_name | identifier | array_literal | annotation; array_literal.Rule = "{" + rvalue_expressions + "}"; field_decl.Rule = annotations + modifiers_then_opt_generic_arg + type_name + identifier + opt_field_assignment + ";" + opt_final_field_assign; opt_field_assignment.Rule = Empty | "=" + rvalue_expression; opt_final_field_assign.Rule = Empty | "{" + assign_expr + ";" + "}"; terminate_decl_or_body.Rule = ";" | ("{" + impl_expressions + "}") | (keyword_default + default_value_literal + ";"); ctor_decl.Rule = annotations + modifiers_then_opt_generic_arg + identifier + "(" + argument_decls + ")" + opt_throws_decl + terminate_decl_or_body; // these Empties can make the structure common to method_decl. method_decl.Rule = annotations + modifiers_then_opt_generic_arg + /*opt_generic_arg_decl*/ type_name + identifier + "(" + argument_decls + ")" + opt_throws_decl + terminate_decl_or_body; impl_expressions.Rule = MakeStarRule(impl_expressions, impl_expression); impl_expression.Rule = call_super | runtime_exception | assign_expr; call_super.Rule = keyword_super + "(" + super_args + ")" + ";"; super_args.Rule = MakeStarRule(super_args, ToTerm(","), default_value_expr); default_value_expr.Rule = keyword_null | default_value_casted | default_value_literal; default_value_casted.Rule = "(" + type_name + ")" + default_value_expr; default_value_literal.Rule = numeric_terminal | "\"\"" | "{" + "}" | keyword_true | keyword_false; runtime_exception.Rule = keyword_throw + keyword_new + identifier + "(\"Stub!\"" + ")" + ";"; new_array.Rule = keyword_new + dotted_identifier + "[" + numeric_literal + "]"; argument_decls.Rule = annotations | MakeStarRule(argument_decls, ToTerm(","), argument_decl); argument_decl.Rule = annotations + type_name + identifier; throws_decl.Rule = keyword_throws + comma_separated_types; comma_separated_types.Rule = MakeStarRule(comma_separated_types, ToTerm(","), type_name); opt_throws_decl.Rule = Empty | throws_decl; type_name.Rule = dotted_identifier | array_type | vararg_type | generic_type; vararg_type.Rule = type_name + T("..."); array_type.Rule = type_name + ("[") + T("]"); generic_definition_arguments_spec.Rule = "<" + generic_definition_arguments + ">"; generic_type.Rule = dotted_identifier + generic_instance_arguments_spec; generic_instance_arguments_spec.Rule = "<" + generic_instance_arguments + ">"; generic_definition_arguments.Rule = MakePlusRule(generic_definition_arguments, ToTerm(","), generic_definition_argument); generic_definition_argument.Rule = identifier + generic_definition_constraints; generic_definition_constraints.Rule = Empty | generic_instance_constraints_extends | generic_instance_constraints_super; generic_instance_arguments.Rule = MakePlusRule(generic_instance_arguments, ToTerm(","), generic_instance_argument); generic_instance_argument.Rule = generic_instance_identifier_or_q + generic_instance_constraints; generic_instance_identifier_or_q.Rule = type_name | T("?"); generic_instance_constraints.Rule = Empty | generic_instance_constraints_extends | generic_instance_constraints_super; generic_instance_constraints_extends.Rule = keyword_extends + generic_instance_constraint_types; generic_instance_constraints_super.Rule = keyword_super + generic_instance_constraint_types; generic_instance_constraint_types.Rule = MakePlusRule(generic_instance_constraint_types, ToTerm("&"), type_name); dotted_identifier.Rule = MakePlusRule(dotted_identifier, ToTerm("."), identifier_wild); numeric_literal.Rule = numeric_terminal; numeric_literal.Rule |= "(" + numeric_literal + "/" + numeric_literal + ")"; value_literal.Rule = string_literal | numeric_literal | keyword_null; identifier_wild.Rule = identifier | "*"; // Define AST node creators Func <string, string> stripGenerics = s => s.IndexOf('<') > 0 ? s.Substring(0, s.IndexOf('<')) : s; single_line_comment.AstConfig.NodeCreator = DoNothing; delimited_comment.AstConfig.NodeCreator = DoNothing; identifier.AstConfig.NodeCreator = (ctx, node) => node.AstNode = node.Token.ValueString; compile_unit.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new JavaPackage(null) { Name = (string)node.ChildNodes [0].AstNode, Types = ((IEnumerable <JavaType>)node.ChildNodes [2].AstNode).ToList() }; }; opt_package_decl.AstConfig.NodeCreator = SelectSingleChild; package_decl.AstConfig.NodeCreator = SelectChildValueAt(1); imports.AstConfig.NodeCreator = CreateArrayCreator <object> (); import.AstConfig.NodeCreator = SelectChildValueAt(1); type_decls.AstConfig.NodeCreator = CreateArrayCreator <JavaType> (); type_decl.AstConfig.NodeCreator = SelectSingleChild; opt_generic_arg_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = node.ChildNodes.Count == 0 ? null : node.ChildNodes [1].AstNode; }; opt_extends_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = node.ChildNodes.Count == 0 ? null : node.ChildNodes [1].AstNode; }; opt_implements_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = node.ChildNodes.Count == 0 ? null : node.ChildNodes [1].AstNode; }; implements_decl.AstConfig.NodeCreator = CreateArrayCreator <string> (); Action <ParseTreeNode, JavaType> fillType = (node, type) => { var modsOrTps = (IEnumerable <object>)node.ChildNodes [1].AstNode; var mods = modsOrTps.OfType <string> (); bool isEnum = node.ChildNodes [2].AstNode as string == "enum"; type.Abstract |= mods.Contains("abstract"); type.Static |= mods.Contains("static"); type.Final |= mods.Contains("final"); type.Visibility = mods.FirstOrDefault(s => s == "public" || s == "protected") ?? ""; type.Name = (string)node.ChildNodes [3].AstNode; type.Deprecated = ((IEnumerable <string>)node.ChildNodes [0].AstNode).Any(v => v == "java.lang.Deprecated" || v == "Deprecated") ? "deprecated" : "not deprecated"; type.TypeParameters = isEnum ? null : (JavaTypeParameters)node.ChildNodes [4].AstNode; type.Members = (IList <JavaMember>)node.ChildNodes [isEnum ? 6 : 7].AstNode; }; enum_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var type = new JavaClass(null) { Extends = "java.lang.Enum", Final = true }; var methods = new JavaMember [] { new JavaMethod(null) { Deprecated = "not deprecated", Name = "valueOf", // Return needs to be filled later, with full package name. Static = true, Visibility = "public", Parameters = new JavaParameter [] { new JavaParameter(null) { Name = "name", Type = "java.lang.String" } }, }, new JavaMethod(null) { Deprecated = "not deprecated", Name = "values", // Return needs to be filled later, with full package name. Static = true, Visibility = "public", Parameters = new JavaParameter [0], } }; fillType(node, type); node.AstNode = type; }; class_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var exts = ((IEnumerable <string>)node.ChildNodes [5].AstNode) ?? Enumerable.Empty <string> (); var impls = ((IEnumerable <string>)node.ChildNodes [6].AstNode) ?? Enumerable.Empty <string> (); var ext = exts.FirstOrDefault() ?? "java.lang.Object"; var type = new JavaClass(null) { Extends = stripGenerics(ext), ExtendsGeneric = ext, Implements = impls.Select(s => new JavaImplements { Name = stripGenerics(s), NameGeneric = s }).ToArray(), }; fillType(node, type); node.AstNode = type; }; interface_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); bool annot = node.ChildNodes [2].AstNode as string == "@interface"; var exts = ((IEnumerable <string>)node.ChildNodes [5].AstNode) ?? Enumerable.Empty <string> (); var impls = ((IEnumerable <string>)node.ChildNodes [6].AstNode) ?? Enumerable.Empty <string> (); var type = new JavaInterface(null) { Implements = exts.Concat(impls).Select(s => new JavaImplements { Name = stripGenerics(s), NameGeneric = s }).ToList(), }; if (annot) { type.Implements.Add(new JavaImplements { Name = "java.lang.annotation.Annotation", NameGeneric = "java.lang.annotation.Annotation" }); } fillType(node, type); node.AstNode = type; }; iface_or_at_iface.AstConfig.NodeCreator = SelectSingleChild; type_body.AstConfig.NodeCreator = SelectChildValueAt(1); type_members.AstConfig.NodeCreator = CreateArrayCreator <JavaMember> (); type_member.AstConfig.NodeCreator = SelectSingleChild; nested_type_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new JavaNestedType(null) { Type = (JavaType)node.ChildNodes [0].AstNode }; }; Action <ParseTreeNode, JavaMethodBase> fillMethodBase = (node, method) => { bool ctor = node.ChildNodes.Count == 8; var modsOrTps = (IEnumerable <object>)node.ChildNodes [1].AstNode; var mods = modsOrTps.OfType <string> (); method.Static = mods.Contains("static"); method.Visibility = mods.FirstOrDefault(s => s == "public" || s == "protected") ?? ""; method.Name = (string)node.ChildNodes [ctor ? 2 : 3].AstNode; method.Parameters = ((IEnumerable <JavaParameter>)node.ChildNodes [ctor ? 4 : 5].AstNode).ToArray(); method.ExtendedSynthetic = mods.Contains("synthetic"); // HACK: Exception "name" can be inconsistent for nested types, and this nested type detection is hacky. Func <string, string> stripPackage = s => { var packageTokens = s.Split('.').TakeWhile(t => !t.Any(c => Char.IsUpper(c))); return(s.Substring(Enumerable.Sum(packageTokens.Select(t => t.Length)) + packageTokens.Count())); }; method.Exceptions = ((IEnumerable <string>)node.ChildNodes [ctor ? 6 : 7].AstNode) ?.Select(s => new JavaException { Type = s, Name = stripPackage(s) }) ?.ToArray(); method.Deprecated = ((IEnumerable <string>)node.ChildNodes [0].AstNode).Any(v => v == "java.lang.Deprecated" || v == "Deprecated") ? "deprecated" : "not deprecated"; method.Final = mods.Contains("final"); method.TypeParameters = modsOrTps.OfType <JavaTypeParameters> ().FirstOrDefault(); }; ctor_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var annots = node.ChildNodes [0].AstNode; var modsOrTps = (IEnumerable <object>)node.ChildNodes [1].AstNode; var mods = modsOrTps.OfType <string> (); var ctor = new JavaConstructor(null); fillMethodBase(node, ctor); node.AstNode = ctor; }; method_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var annots = node.ChildNodes [0].AstNode; var modsOrTps = (IEnumerable <object>)node.ChildNodes [1].AstNode; var mods = modsOrTps.OfType <string> (); var method = new JavaMethod(null) { Return = (string)node.ChildNodes [2].AstNode, Abstract = mods.Contains("abstract"), Native = mods.Contains("native"), Synchronized = mods.Contains("synchronized"), ExtendedSynthetic = mods.Contains("synthetic"), }; fillMethodBase(node, method); node.AstNode = method; }; field_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var annots = node.ChildNodes [0].AstNode; var modsOrTps = (IEnumerable <object>)node.ChildNodes [1].AstNode; var mods = modsOrTps.OfType <string> (); var value = node.ChildNodes [4].AstNode?.ToString(); var type = (string)node.ChildNodes [2].AstNode; node.AstNode = new JavaField(null) { Static = mods.Contains("static"), Visibility = mods.FirstOrDefault(s => s == "public" || s == "protected") ?? "", Type = stripGenerics(type), TypeGeneric = type, Name = (string)node.ChildNodes [3].AstNode, Deprecated = ((IEnumerable <string>)node.ChildNodes [0].AstNode).Any(v => v == "java.lang.Deprecated" || v == "Deprecated") ? "deprecated" : "not deprecated", Value = value == "null" ? null : value, // null will not be explicitly written. Volatile = mods.Contains("volatile"), Final = mods.Contains("final"), Transient = mods.Contains("transient"), }; }; opt_field_assignment.AstConfig.NodeCreator = (ctx, node) => node.AstNode = node.ChildNodes.Count > 0 ? node.ChildNodes [1].AstNode : null; opt_final_field_assign.AstConfig.NodeCreator = (ctx, node) => node.AstNode = node.ChildNodes.Count > 0 ? node.ChildNodes [1].AstNode : null; static_ctor_decl.AstConfig.NodeCreator = DoNothing; // static constructors are ignorable. enum_body.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var ml = new List <JavaMember> (); foreach (var c in node.ChildNodes) { ml.AddRange((IEnumerable <JavaMember>)c.AstNode); } node.AstNode = ml; }; enum_members_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); if (node.ChildNodes.Count > 0) { node.AstNode = ((IEnumerable <string>)node.ChildNodes [0].AstNode) .Select(s => new JavaField(null) { Name = s, Final = true, Deprecated = "not deprecated", Static = true, // Type needs to be filled later, with full package name. Visibility = "public" }); } }; enum_member_initializers.AstConfig.NodeCreator = CreateArrayCreator <string> (); enum_member_initializer.AstConfig.NodeCreator = SelectChildValueAt(1); opt_enum_braces.AstConfig.NodeCreator = DoNothing; terminate_decl_or_body.AstConfig.NodeCreator = DoNothing; // method/ctor body doesn't matter. assignments.AstConfig.NodeCreator = CreateArrayCreator <object> (); assignment.AstConfig.NodeCreator = SelectChildValueAt(0); assign_expr.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new KeyValuePair <string, string?> ((string)node.ChildNodes [0].AstNode, node.ChildNodes [2].AstNode?.ToString()); }; rvalue_expressions.AstConfig.NodeCreator = CreateArrayCreator <object> (); rvalue_expression.AstConfig.NodeCreator = SelectSingleChild; array_literal.AstConfig.NodeCreator = CreateStringFlattener(); annotations.AstConfig.NodeCreator = CreateArrayCreator <string> (); annotation.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node.ChildNodes [1]); // we only care about name. node.AstNode = node.ChildNodes [1].AstNode; }; opt_annotation_args.AstConfig.NodeCreator = DoNothing; annotation_value_assignments.AstConfig.NodeCreator = DoNothing; annot_assign_expr.AstConfig.NodeCreator = DoNothing; modifiers_then_opt_generic_arg.AstConfig.NodeCreator = CreateArrayCreator <object> (); modifier_or_generic_arg.AstConfig.NodeCreator = SelectSingleChild; modifiers.AstConfig.NodeCreator = CreateArrayCreator <string> (); modifier.AstConfig.NodeCreator = CreateStringFlattener(); argument_decls.AstConfig.NodeCreator = CreateArrayCreator <JavaParameter> (); argument_decl.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new JavaParameter(null) { Type = (string)node.ChildNodes [1].AstNode, Name = (string)node.ChildNodes [2].AstNode }; }; opt_throws_decl.AstConfig.NodeCreator = SelectSingleChild; throws_decl.AstConfig.NodeCreator = SelectChildValueAt(1); comma_separated_types.AstConfig.NodeCreator = CreateArrayCreator <string> (); type_name.AstConfig.NodeCreator = SelectSingleChild; dotted_identifier.AstConfig.NodeCreator = CreateStringFlattener("."); array_type.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = node.ChildNodes [0].AstNode + "[]"; }; vararg_type.AstConfig.NodeCreator = CreateStringFlattener(); generic_type.AstConfig.NodeCreator = CreateStringFlattener(); generic_definition_arguments_spec.AstConfig.NodeCreator = SelectChildValueAt(1); generic_instance_arguments_spec.AstConfig.NodeCreator = (ctx, node) => { // It is distinct from generic type parameters definition. ProcessChildren(ctx, node); node.AstNode = "<" + string.Join(", ", (IEnumerable <string>)node.ChildNodes [1].AstNode) + ">"; }; generic_definition_arguments.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new JavaTypeParameters((JavaMethod?)null) { TypeParameters = node.ChildNodes.Select(c => c.AstNode).Cast <JavaTypeParameter> ().ToList() }; }; generic_definition_argument.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); node.AstNode = new JavaTypeParameter(null) { Name = (string)node.ChildNodes [0].AstNode, GenericConstraints = (JavaGenericConstraints)node.ChildNodes [1].AstNode }; }; generic_definition_constraints.AstConfig.NodeCreator = SelectSingleChild; generic_instance_arguments.AstConfig.NodeCreator = CreateArrayCreator <string> (); generic_instance_argument.AstConfig.NodeCreator = CreateStringFlattener(); generic_instance_identifier_or_q.AstConfig.NodeCreator = SelectSingleChild; generic_instance_constraints.AstConfig.NodeCreator = (ctx, node) => { ProcessChildren(ctx, node); var c = (JavaGenericConstraints?)node.ChildNodes.FirstOrDefault()?.AstNode; if (c != null) { node.AstNode = " " + c.BoundsType + " " + string.Join(" & ", c.GenericConstraints.Select(cc => cc.Type)); } }; AstNodeCreator createGenericConstaints = (ctx, node) => { ProcessChildren(ctx, node); var cl = ((IEnumerable <string>)node.ChildNodes [1].AstNode).Select(s => new JavaGenericConstraint { Type = s }); node.AstNode = new JavaGenericConstraints() { BoundsType = (string)node.ChildNodes [0].AstNode, GenericConstraints = cl.Any() ? cl.ToArray() : null, }; }; generic_instance_constraints_extends.AstConfig.NodeCreator = createGenericConstaints; generic_instance_constraints_super.AstConfig.NodeCreator = createGenericConstaints; generic_instance_constraint_types.AstConfig.NodeCreator = CreateArrayCreator <string> (); impl_expressions.AstConfig.NodeCreator = CreateArrayCreator <object> (); impl_expression.AstConfig.NodeCreator = SelectSingleChild; // each expression item is not seriously processed. // They are insignificant except for consts, and for consts they are just string values. call_super.AstConfig.NodeCreator = CreateStringFlattener(); super_args.AstConfig.NodeCreator = CreateStringFlattener(); default_value_expr.AstConfig.NodeCreator = CreateStringFlattener(); default_value_casted.AstConfig.NodeCreator = CreateStringFlattener(); default_value_literal.AstConfig.NodeCreator = CreateStringFlattener(); new_array.AstConfig.NodeCreator = DoNothing; runtime_exception.AstConfig.NodeCreator = CreateStringFlattener(); Func <string, string, string> stripTail = (s, t) => s.EndsWith(t, StringComparison.Ordinal) ? s.Substring(0, s.Length - t.Length) : s; numeric_terminal.AstConfig.NodeCreator = (ctx, node) => node.AstNode = stripTail(stripTail(node.Token.Text, "L"), "f"); numeric_literal.AstConfig.NodeCreator = CreateStringFlattener(); string_literal.AstConfig.NodeCreator = (ctx, node) => node.AstNode = '"' + node.Token.ValueString + '"'; value_literal.AstConfig.NodeCreator = SelectSingleChild; identifier_wild.AstConfig.NodeCreator = SelectSingleChild; this.Root = compile_unit; }
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"); CilMain.JavaClasses.Add(infoClass); } 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 BuildGenericProxy2(CilInterfaceMethod ifcMethod, CilMethod targetMethod, bool parentField, CilType intoType, JavaClass ifcClass) { // // create proxy method // var targetMethod2 = targetMethod.WithGenericParameters; var ifcMethod2 = ifcMethod.Method.WithGenericParameters; var newMethod = new JavaMethod(ifcClass, targetMethod2); newMethod.Name = ifcMethod2.Name; newMethod.Flags = JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_BRIDGE; var code = newMethod.Code = new JavaCode(); code.Method = newMethod; code.Instructions = new List <JavaCode.Instruction>(); // // push a reference to the parent object // code.NewInstruction(0x19 /* aload */, null, (int)0); if (parentField) { code.NewInstruction(0xB4 /* getfield */, new JavaType(0, 0, ifcClass.Name), new JavaFieldRef(ParentFieldName, intoType)); } // // push all other parameters // int numArgs = newMethod.Parameters.Count; int index = 1; int maxStack = 1; for (int i = 0; i < numArgs; i++) { var ifcArg = ifcMethod2.Parameters[i].Type; code.NewInstruction(ifcArg.LoadOpcode, null, (int)index); index += ifcArg.Category; var clsArg = (CilType)targetMethod2.Parameters[i].Type; if (JavaType.ObjectType.Equals(ifcArg)) { if (!clsArg.IsReference) { var boxedArg = new BoxedType(clsArg, false); code.NewInstruction(0xC0 /* checkcast */, boxedArg, null); boxedArg.GetValue(code); } else if (!JavaType.ObjectType.Equals(clsArg)) { code.NewInstruction(0xC0 /* checkcast */, clsArg, null); } // a parameter in the target method may be a concrete type, // but if it is a generic java.lang.Object in the interface, // then it must be a generic java.lang.Object in the proxy newMethod.Parameters[i] = new JavaFieldRef("", ifcArg); } maxStack += clsArg.Category; } // // invoke proxy target method // code.NewInstruction(0xB6 /* invokevirtual */, intoType, targetMethod2); // // return value from method // var clsRet = (CilType)targetMethod2.ReturnType; var ifcRet = ifcMethod2.ReturnType; if (JavaType.ObjectType.Equals(ifcRet)) { if (!clsRet.IsReference) { var boxedArg = new BoxedType(clsRet, false); boxedArg.BoxValue(code); } // the return value in the target method may be a concrete type, // but if it is a generic java.lang.Object in the interface, // then it must also be a generic java.lang.Object in the proxy newMethod.ReturnType = ifcRet; code.NewInstruction(ifcRet.ReturnOpcode, null, null); } else { code.NewInstruction(clsRet.ReturnOpcode, null, null); } code.MaxLocals = index; code.MaxStack = maxStack; ifcClass.Methods.Add(newMethod); }
/// <summary> /// Initializes a new instance of the <see cref="CacheChannelEventListenerCallback"/> class. /// </summary> /// <param name="cacheChannelEventListener">The associated <see cref="I:Com.Tridion.Cache.ICacheChannelEventListener" /></param> public CacheChannelEventListenerCallback(ICacheChannelEventListener cacheChannelEventListener) { mCacheChannelEventListener = cacheChannelEventListener; mConnectCallback = new GenericCallback((out int return_type, out jvalue return_value, IntPtr input) => { try { mCacheChannelEventListener.HandleConnect(); // Void return_value = new jvalue(); return_type = 0; } catch (Exception exception) { // Wrap the exception for Java return_value = jvalue.CreateCBRetVal(exception); // Object return_type = 1; } return(0); }); mDisconnectCallback = new GenericCallback((out int return_type, out jvalue return_value, IntPtr input) => { try { mCacheChannelEventListener.HandleConnect(); // Void return_value = new jvalue(); return_type = 0; } catch (Exception exception) { // Wrap the exception for Java return_value = jvalue.CreateCBRetVal(exception); // Object return_type = 1; } return(0); }); mRemoteEventCallback = new GenericCallback((out int return_type, out jvalue return_value, IntPtr input) => { try { CacheEvent typedInstance = (CacheEvent)JavaClass.GetTypedInstance(typeof(CacheEvent), jvalue.From(input).l); mCacheChannelEventListener.HandleRemoteEvent(typedInstance); // Void return_value = new jvalue(); return_type = 0; } catch (Exception exception) { // Wrap the exception for Java return_value = jvalue.CreateCBRetVal(exception); // Object return_type = 1; } return(0); }); base.JObject = mConstructor.construct(0, mConnectCallback, mDisconnectCallback, mRemoteEventCallback); }
public bool CreateCilTypeForClass(JavaClass jclass) { var name = jclass.Name; if (typeMap.TryGetValue(name, out _) || jclass.IsInnerClass() && (name.StartsWith("java.lang.Object$") || name.StartsWith("java.lang.String$"))) { Console.WriteLine($"skipping duplicate class '{name}'"); return(false); } string nsName, clsName; TypeAttributes attrs = 0; if (jclass.IsInnerClass()) { nsName = string.Empty; clsName = jclass.OuterAndInnerClasses[0].InnerShortName; if (!string.IsNullOrEmpty(clsName)) { int idx = name.LastIndexOf('$'); if (idx != -1 && idx + 1 < name.Length) { clsName = name.Substring(idx + 1); } } if (string.IsNullOrEmpty(clsName) || (!Char.IsLetter(clsName[0]))) { clsName = "autogenerated_" + jclass.GetHashCode().ToString("X8"); } if ((jclass.Flags & JavaAccessFlags.ACC_PUBLIC) != 0) { attrs = TypeAttributes.NestedPublic; } else if ((jclass.Flags & JavaAccessFlags.ACC_PRIVATE) != 0) { attrs = TypeAttributes.NestedPrivate; } else if ((jclass.Flags & JavaAccessFlags.ACC_PROTECTED) != 0) { attrs = TypeAttributes.NestedFamORAssem; } else { attrs = TypeAttributes.NestedAssembly; } } else { int n = jclass.PackageNameLength; nsName = name.Substring(0, n); if (name[n] == '.') { n++; } clsName = name.Substring(n); if ((jclass.Flags & JavaAccessFlags.ACC_PUBLIC) != 0) { attrs |= TypeAttributes.Public; } } if ((jclass.Flags & JavaAccessFlags.ACC_ABSTRACT) != 0) { attrs |= TypeAttributes.Abstract; } if ((jclass.Flags & JavaAccessFlags.ACC_INTERFACE) != 0) { attrs |= TypeAttributes.Interface; } if ((jclass.Flags & JavaAccessFlags.ACC_FINAL) != 0) { attrs |= TypeAttributes.Sealed; } var newType = new TypeDefinition(nsName, clsName, attrs); newType.CustomAttributes.Add(new CustomAttribute(retainNameAttributeConstructor)); typeMap[name] = newType; return(true); }
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 static void ImportMethods(JavaClass jclass, TypeDefinition cilType, int numCastableInterfaces) { if (cilType.HasMethods) { int n = cilType.Methods.Count; if (n > 0) { jclass.Methods = new List <JavaMethod>(n); for (int i = 0; i < n; i++) { var defMethod = cilType.Methods[i]; /* * if (defMethod.HasCustomAttribute("Discard")) * continue; // if decorated with [java.attr.Discard], don't export to java */ var genericMark = CilMain.GenericStack.Mark(); var myMethod = CilMain.GenericStack.EnterMethod(defMethod); var newMethod = new JavaMethod(jclass, myMethod.WithGenericParameters); newMethod.Flags = AttributesToAccessFlags( defMethod.Attributes, defMethod.HasOverrides, (cilType.HasNestedTypes || cilType.HasGenericParameters)); if (myMethod.IsStatic & myMethod.IsConstructor) { newMethod.Flags &= ~(JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_PRIVATE | JavaAccessFlags.ACC_PROTECTED); } if (defMethod.HasBody) { CilMain.Where.Push($"method '{defMethod.Name}'"); CodeBuilder.BuildJavaCode(newMethod, myMethod, defMethod, numCastableInterfaces); if ((defMethod.ImplAttributes & MethodImplAttributes.Synchronized) != 0) { // if method is decorated with [MethodImplOptions.Synchronized], // create a wrapper method that locks appropriately jclass.Methods.Add( CodeBuilder.CreateSyncWrapper(newMethod, myMethod.DeclType)); } else if (defMethod.Name == "Finalize" && (!defMethod.HasParameters) && defMethod.IsVirtual) { // if method is a finalizer, create a wrapper method that // checks if finalization was suppressed for the object CodeBuilder.CreateSuppressibleFinalize( newMethod, myMethod.DeclType, jclass); } if (defMethod.IsVirtual) { InterfaceBuilder.BuildOverloadProxy( cilType, defMethod, myMethod, jclass); } else if (!myMethod.IsConstructor) { newMethod.Flags |= JavaAccessFlags.ACC_FINAL; } CilMain.Where.Pop(); } else { if ((!defMethod.IsAbstract) && (defMethod.IsInternalCall || defMethod.IsPInvokeImpl)) { // skip native methods continue; } // clear ACC_STATIC and access, set ACC_ABSTRACT and ACC_PUBLIC newMethod.Flags = (newMethod.Flags | JavaAccessFlags.ACC_ABSTRACT | JavaAccessFlags.ACC_PUBLIC) & ~(JavaAccessFlags.ACC_STATIC | JavaAccessFlags.ACC_PRIVATE | JavaAccessFlags.ACC_PROTECTED); } jclass.Methods.Add(newMethod); CilMain.GenericStack.Release(genericMark); if (myMethod.IsConstructor) { var dummyClass = CreateDummyClassForConstructor(myMethod, jclass); if (dummyClass != null) { CilMain.JavaClasses.Add(dummyClass); } } else if (myMethod.WithGenericParameters != myMethod && (!myMethod.IsRetainName)) { jclass.Methods.Add( Delegate.CreateCapturingBridgeMethod( newMethod, myMethod.Parameters, cilType.IsInterface)); } } } } else { jclass.Methods = new List <JavaMethod>(0); } JavaClass CreateDummyClassForConstructor(CilMethod theMethod, JavaClass theClass) { if (!theMethod.HasDummyClassArg) { return(null); } return(CilMain.CreateInnerClass( theClass, theMethod.Parameters[ theMethod.Parameters.Count - 1].Type.ClassName)); } }
/// <summary> /// Gets the names of the interfaces of the given class. /// </summary> /// <param name="jc">The java class.</param> /// <returns>The names of the interfaces of the class.</returns> public static string[] GetInterfaces(this JavaClass jc) { Guard.NotNull(ref jc, nameof(jc)); return(jc.Interfaces.Select(x => jc.GetConstant <JavaConstantUtf8>(jc.GetConstant <JavaConstantClass>(x).NameIndex).Value).ToArray()); }
public static void CreateProject(List <JavaObject> javaObjects, string targetpath, string folderName) { //string subdir = $"C:/Users/sofia/Favorites/FolderTest"; string subdir = $"{targetpath}/{folderName}"; // If directory does not exist, create it. if (!Directory.Exists(subdir)) { Directory.CreateDirectory(subdir); } foreach (var item in javaObjects) { // TODO // einzelne Unterpunkte!; //string pathPackages = @"C:/Users/sofia/Favorites/FolderTest"; string pathPackages = subdir; var splitPath = item.Package.Split('.'); foreach (var p in splitPath) { pathPackages = pathPackages + "/" + p; if (!Directory.Exists(pathPackages)) { Directory.CreateDirectory(pathPackages); } } } foreach (var item in javaObjects) { string pathPackages = ""; var splitPath = item.Package.Split('.'); foreach (var p in splitPath) { pathPackages = pathPackages + "/" + p; if (!Directory.Exists(pathPackages)) { Directory.CreateDirectory(pathPackages); } } string path = $"{subdir}/{pathPackages}/{item.Name}.java"; //string path = @"C:/Users/sofia/Favorites/FolderTest/" + pathPackages + "/" + item.Name + ".java"; if (!File.Exists(path)) { // Create a file to write to. using (StreamWriter sw = File.CreateText(path)) { sw.WriteLine($"package {item.Package};"); sw.WriteLine(); foreach (var impl in item.ObjectsToImport) { sw.WriteLine("import " + impl.Package + "." + impl.Name + ";"); } if (item.GetType().ToString().Equals("UMJA.Utility.JavaClass")) { JavaClass javaClass = (JavaClass)item; string imp = (javaClass.Implements.Count == 0) ? " " : " implements"; foreach (var i in javaClass.Implements) { imp = imp + " " + i.Name; } sw.WriteLine(); sw.WriteLine("public class " + item.Name + imp + " {"); foreach (var vari in javaClass.Variables) { var final = (vari.IsFinal) ? "final" : ""; var priv = (vari.IsPrivate) ? "private" : "public"; var stat = (vari.IsStatic) ? "static" : ""; string equalsPart = (vari.DefinedValue != null && vari.DefinedValue != string.Empty) ? $" = {vari.DefinedValue}" : ""; if (equalsPart.Equals("") && vari.IsFinal) { equalsPart = $" = new {vari.ObjectType}()"; } sw.WriteLine(priv + " " + stat + " " + final + " " + vari.ObjectType + " " + vari.Name + equalsPart + ";"); } foreach (var method in javaClass.Methods) { var priv = (method.IsPrivate) ? "private" : "public"; var stat = (method.IsStatic) ? "static" : ""; string parameter = ""; foreach (var variable in method.Parameters) { parameter += variable.ObjectType + " " + variable.Name + ", "; } if (parameter.Length > 0) { parameter = parameter.Substring(0, parameter.Length - 2); } if (Object.Equals(method.Name, "toString")) { sw.WriteLine(Environment.NewLine + "@Override"); sw.WriteLine(priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "(" + parameter + ")" + " {" + Environment.NewLine + " return \"\";" + Environment.NewLine + "}"); } else if (method.Override) { sw.WriteLine(Environment.NewLine + "@Override"); sw.WriteLine(priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "(" + parameter + ")" + " {" + Environment.NewLine + " throw new UnsupportedOperationException(\"Not supported yet.\"); //To change body of generated methods, choose Tools | Templates." + Environment.NewLine + "}"); } else if (method.Name.StartsWith("get") && javaClass.Variables.FindAll(x => method.Name.ToLower().Contains(x.Name.ToLower())).Count != 0) { sw.WriteLine(Environment.NewLine + priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "() {"); sw.WriteLine($"return {javaClass.Variables.FindAll(x => method.Name.ToLower().Contains(x.Name.ToLower())).First().Name};"); sw.WriteLine("}"); } else if (method.Name.StartsWith("set") && javaClass.Variables.FindAll(x => method.Name.ToLower().Contains(x.Name.ToLower())).Count > 0) { sw.WriteLine(Environment.NewLine + priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "(" + parameter + ")" + " {"); sw.WriteLine($"this.{method.Parameters[0].Name} = {method.Parameters[0].Name};"); sw.WriteLine("}"); } else { sw.WriteLine(Environment.NewLine + priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "(" + parameter + ")" + " {" + Environment.NewLine + Environment.NewLine + "}"); } } if (javaClass.HasConstructor) { var variablesForConstSB = new StringBuilder(); javaClass.Variables.FindAll(x => !x.IsStatic).ToList().ForEach(x => variablesForConstSB.Append($"{x.ObjectType} {x.Name}, ")); sw.WriteLine($"public {javaClass.Name}({variablesForConstSB.ToString().Remove(variablesForConstSB.ToString().Length - 2, 2)}) " + "{"); javaClass.Variables.ForEach(x => sw.WriteLine($"this.{x.Name} = {x.Name};")); sw.WriteLine("}"); sw.WriteLine(""); } if (javaClass.HasGetter) { javaClass.Variables.ForEach(x => sw.WriteLine($"public {x.ObjectType} get{x.Name.ToCharArray()[0].ToString().ToUpper()}{x.Name.Remove(0, 1)}() " + "{" + Environment.NewLine + $" return {x.Name};" + Environment.NewLine + "}")); } if (javaClass.HasSetter) { javaClass.Variables.ForEach(x => sw.WriteLine($"public {x.ObjectType} set{x.Name.ToCharArray()[0].ToString().ToUpper()}{x.Name.Remove(0, 1)}({x.ObjectType} {x.Name}) " + "{" + Environment.NewLine + $" this.{x.Name} = {x.Name};" + Environment.NewLine + "}")); } sw.WriteLine("}"); guiLog($"Die Klasse {javaClass.Name} wurde Compiliert"); } else if (item.GetType().ToString().Equals("UMJA.Utility.JavaEnumeration")) { JavaEnumeration javaEnumeration = (JavaEnumeration)item; sw.WriteLine("public enum " + item.Name + "{"); sw.WriteLine(javaEnumeration.Values); sw.WriteLine("}"); guiLog($"Das Enum {javaEnumeration.Name} wurde Compiliert"); } else if (item.GetType().ToString().Equals("UMJA.Utility.JavaInterface")) { JavaInterface javaClass = (JavaInterface)item; sw.WriteLine("public interface " + item.Name + "{"); foreach (var vari in javaClass.Variables) { var final = (vari.IsFinal) ? "final" : ""; var priv = (vari.IsPrivate) ? "private" : "public"; var stat = (vari.IsStatic) ? "static" : ""; string equalsPart = (vari.DefinedValue != null && vari.DefinedValue != string.Empty) ? $" = {vari.DefinedValue}" : ""; if (equalsPart.Equals("") && vari.IsFinal) { equalsPart = $" = new {vari.ObjectType}()"; } sw.WriteLine(priv + " " + stat + " " + final + " " + vari.ObjectType + " " + vari.Name + equalsPart + ";"); } foreach (var method in javaClass.Methods) { var priv = (method.IsPrivate) ? "private" : "public"; var stat = (method.IsStatic) ? "static" : ""; string parameter = ""; foreach (var variable in method.Parameters) { parameter += parameter + variable.ObjectType + " " + variable.Name + ", "; } if (parameter.Length > 0) { parameter = parameter.Substring(0, parameter.Length - 2); } sw.WriteLine(priv + " " + stat + " " + " " + method.ReturnObject + " " + method.Name + "(" + parameter + ");"); } sw.WriteLine("}"); guiLog($"Das Interface {javaClass.Name} wurde Compiliert"); } } } } guiLog("Das Projekt wurde erfolgreich erstellt!"); }
public static JavaClass FixClass(JavaClass fromClass, CilType fromType) { JavaType interfaceType = InterfaceType(fromType); JavaClass interfaceClass = null; var fromMethods = fromClass.Methods; for (int i = fromMethods.Count; i-- > 0;) { var nm = fromMethods[i].Name; if (nm == "BeginInvoke" || nm == "EndInvoke") { fromClass.Methods.RemoveAt(i); } } foreach (var method in fromMethods) { if ((method.Flags & JavaAccessFlags.ACC_STATIC) == 0 && method.Code == null) { if (method.Name == "<init>") { GenerateConstructor(method, fromType); } else if (method.Name == "Invoke") { if (interfaceClass != null) { break; } interfaceClass = MakeInterface(fromClass, method, interfaceType.ClassName); GenerateInvoke(method, fromType, interfaceType); } /*else if (method.Name == "BeginInvoke") * { * if (interfaceClass == null) * break; * * GenerateBeginInvoke(); * continue; * } * else if (method.Name == "EndInvoke") * { * GenerateEndInvoke(); * continue; * }*/ else { break; } method.Flags &= ~JavaAccessFlags.ACC_ABSTRACT; } } if (interfaceClass == null) { throw CilMain.Where.Exception("invalid delegate class"); } return(interfaceClass); // // // JavaClass MakeInterface(JavaClass fromClass, JavaMethod fromMethod, string newName) { var newClass = CilMain.CreateInnerClass(fromClass, newName, JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_ABSTRACT | JavaAccessFlags.ACC_INTERFACE); var newMethod = new JavaMethod(newClass, fromMethod); newMethod.Flags = JavaAccessFlags.ACC_PUBLIC | JavaAccessFlags.ACC_ABSTRACT; if (IsPrimitive(newMethod.ReturnType)) { // primitive return value is translated to java.lang.Object, // because the delegate target may return a generic type that // is specialized for the primitive type in the delegate. // see also GenerateInvoke and LoadFunction newMethod.ReturnType = JavaType.ObjectType; } newClass.Methods.Add(newMethod); return(newClass); } // // // void GenerateConstructor(JavaMethod method, CilType dlgType) { var code = method.Code = new JavaCode(); code.Method = method; code.Instructions = new List <Instruction>(); if (dlgType.HasGenericParameters) { code.StackMap = new JavaStackMap(); var genericMark = CilMain.GenericStack.Mark(); CilMain.GenericStack.EnterMethod(dlgType, method, true); // initialize the generic type field GenericUtil.InitializeTypeField(dlgType, code); CilMain.GenericStack.Release(genericMark); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); } code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0x19 /* aload_1 */, null, (int)1); code.NewInstruction(0x19 /* aload_2 */, null, (int)2); code.NewInstruction(0xB7 /* invokespecial */, new JavaType(0, 0, method.Class.Super), new JavaMethodRef("<init>", JavaType.VoidType, JavaType.ObjectType, JavaType.ObjectType)); code.NewInstruction(0xB1 /* return (void) */, null, null); if (code.MaxStack < 3) { code.MaxStack = 3; } code.MaxLocals = 3 + dlgType.GenericParametersCount; } // // // void GenerateInvoke(JavaMethod method, CilType dlgType, JavaType ifcType) { var delegateType = new JavaType(0, 0, "system.Delegate"); var code = method.Code = new JavaCode(); code.Method = method; code.Instructions = new List <Instruction>(); code.StackMap = new JavaStackMap(); code.StackMap.SetLocal(0, dlgType); int index = 1; for (int i = 0; i < method.Parameters.Count; i++) { var paramType = (CilType)method.Parameters[i].Type; code.StackMap.SetLocal(index, paramType); index += paramType.Category; } code.StackMap.SaveFrame((ushort)0, false, CilMain.Where); // // step 1, call the target method through the interface reference // stored in the 'invokable' field of the system.Delegate class // code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, delegateType, new JavaFieldRef("invokable", JavaType.ObjectType)); code.NewInstruction(0xC0 /* checkcast */, ifcType, null); code.StackMap.PushStack(JavaType.ObjectType); // push method parameters 'invokeinterface' index = 1; for (int i = 0; i < method.Parameters.Count; i++) { var paramType = (CilType)method.Parameters[i].Type; code.NewInstruction(paramType.LoadOpcode, null, index); code.StackMap.PushStack(paramType); if (paramType.IsGenericParameter && (!paramType.IsByReference)) { // invoke the helper method which identifies our boxed // primitives and re-boxes them as java boxed values. // see also: GenericType::DelegateParameterin baselib. GenericUtil.LoadMaybeGeneric( paramType.GetMethodGenericParameter(), code); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, DelegateParameterMethod); code.StackMap.PopStack(CilMain.Where); } index += paramType.Category; } var returnType = (CilType)method.ReturnType; if (IsPrimitive(returnType)) { // primitive return value is translated to java.lang.Object, // because the delegate target may return a generic type that // is specialized for the primitive type in the delegate. // see also GenerateInvoke and LoadFunction var adjustedMethod = new JavaMethodRef( method.Name, JavaType.ObjectType, method.Parameters); code.NewInstruction(0xB9 /* invokeinterface */, ifcType, adjustedMethod); } else { code.NewInstruction(0xB9 /* invokeinterface */, ifcType, method); } code.StackMap.ClearStack(); code.StackMap.PushStack(returnType); // check if this delegate has a 'following' delegate, // attached via system.MulticastDelegate.CombineImpl code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, delegateType, new JavaFieldRef("following", delegateType)); code.NewInstruction(0xC7 /* ifnonnull */, null, (ushort)1); if (returnType.IsGenericParameter && (!returnType.IsByReference)) { GenericUtil.LoadMaybeGeneric( returnType.GetMethodGenericParameter(), code); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, DelegateReturnValueMethod); code.StackMap.PopStack(CilMain.Where); } else if (IsPrimitive(returnType)) { // if the delegate returns a primitive type, we need to unbox // the object returned by the method we just called. it will be // a java boxed primitive (e.g. java.lang.Integer) if the called // method actually returns a primitive, due to the boxing done // by the invokedynamic mechanism. if the called method returns // a generic type, it will be our boxed type, e.g. system.Int32. // // see also DelegateReturnValueX helper methods in baselib, // and MakeInterface and LoadFunction in this file. var helperMethod = new JavaMethodRef( DelegateReturnValueMethod.Name + returnType.ToDescriptor(), returnType, JavaType.ObjectType); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, helperMethod); } code.NewInstruction(returnType.ReturnOpcode, null, index); code.StackMap.PopStack(CilMain.Where); // // step 2 // // if this delegate has a 'following' delegate, then we need to // call it, but first get rid of the return value on the stack // byte popOpcode; if (returnType.Equals(JavaType.VoidType)) { popOpcode = 0x00; // nop } else // select 0x57 pop, or 0x58 pop2 { var adjustedReturnType = IsPrimitive(returnType) ? JavaType.ObjectType : returnType; code.StackMap.PushStack(adjustedReturnType); popOpcode = (byte)(0x56 + returnType.Category); } code.NewInstruction(popOpcode, null, null, (ushort)1); code.StackMap.SaveFrame((ushort)1, true, CilMain.Where); // now call the Invoke method on the 'following' delegate code.NewInstruction(0x19 /* aload_0 */, null, (int)0); code.NewInstruction(0xB4 /* getfield */, delegateType, new JavaFieldRef("following", delegateType)); code.NewInstruction(0xC0 /* checkcast */, dlgType, null); // push all method parameters for 'invokevirtual' index = 1; for (int i = 0; i < method.Parameters.Count; i++) { var paramType = (CilType)method.Parameters[i].Type; code.NewInstruction(paramType.LoadOpcode, null, index); if (paramType.IsGenericParameter && (!paramType.IsByReference)) { // invoke the helper method which identifies our boxed // primitives and re-boxes them as java boxed values. // see also: GenericType::DelegateParameterin baselib. GenericUtil.LoadMaybeGeneric( paramType.GetMethodGenericParameter(), code); code.NewInstruction(0xB8 /* invokestatic */, SystemDelegateUtilType, DelegateParameterMethod); } index += paramType.Category; } code.NewInstruction(0xB6 /* invokevirtual */, dlgType, method); code.NewInstruction(returnType.ReturnOpcode, null, index); code.StackMap.ClearStack(); code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where); code.MaxLocals = index; } // // // /*void GenerateBeginInvoke() * { * }*/ // // // /*void GenerateEndInvoke() * { * }*/ }
public void GenerateCode(JavaCodeConfig javaCodeConfig, JavaClass createdJavaBean) { CSharpTemplate template = GetTemplate(javaCodeConfig); IRazorEngineCompiledTemplate <RazorEngineTemplateBase <JavaCodeConfig> > codeTemplate = null; lock (this) { javaCodeConfig.JavaClass = createdJavaBean; string rootDir = String.Empty; string result = String.Empty; string fileName = string.Empty; Action action = () => { codeTemplate = null; codeTemplate = codeTemplate ?? (javaCodeConfig.ForModel ? template.modelTemplate : null); codeTemplate = codeTemplate ?? (javaCodeConfig.ForService ? template.serviceTemplate : null); codeTemplate = codeTemplate ?? (javaCodeConfig.ForServiceImpl ? template.serviceImplTemplate : null); codeTemplate = codeTemplate ?? (javaCodeConfig.ForController ? template.controllerTemplate : null); if (codeTemplate == null) { Console.WriteLine(""); } result = codeTemplate.Run(instance => { instance.Model = javaCodeConfig; }); Console.WriteLine(result); string filePath = rootDir + Path.DirectorySeparatorChar + fileName + ".java"; if (File.Exists(filePath)) { File.Delete(filePath); } File.WriteAllText(filePath, result, new UTF8Encoding(false)); }; if (javaCodeConfig.GeneralModel) { javaCodeConfig.Reset(); javaCodeConfig.ForModel = true; rootDir = CodeUtil.PrepareCodeRoot(javaCodeConfig.ModelJavaDiretory, javaCodeConfig.ModelPackageName); fileName = javaCodeConfig.ModelName; action(); } if (javaCodeConfig.GeneralService) { javaCodeConfig.Reset(); javaCodeConfig.ForService = true; rootDir = CodeUtil.PrepareCodeRoot(javaCodeConfig.ModelJavaDiretory, javaCodeConfig.ServicePackageName); fileName = javaCodeConfig.ServiceName; action(); } if (javaCodeConfig.GeneralServiceImpl) { javaCodeConfig.Reset(); javaCodeConfig.ForServiceImpl = true; rootDir = CodeUtil.PrepareCodeRoot(javaCodeConfig.ModelJavaDiretory, javaCodeConfig.ServiceImplPackageName); fileName = javaCodeConfig.ServiceImplName; action(); } if (javaCodeConfig.GeneralController) { javaCodeConfig.Reset(); javaCodeConfig.ForController = true; rootDir = CodeUtil.PrepareCodeRoot(javaCodeConfig.ModelJavaDiretory, javaCodeConfig.ControllerPackageName); fileName = javaCodeConfig.ControllerName; action(); } } }
protected bool Equals(JavaClass other) { return(string.Equals(Name, other.Name)); }
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); } }
/// <summary> /// Gets a java class by it's classname. /// </summary> /// <returns>False if not found.</returns> internal bool TryGetJavaClass(string className, out JavaClass jClass) { return javaClasses.TryGetValue(className, out jClass); }
private string TraverseClass(JavaClass javaClass) { return(TraverseClassOrInterface(javaClass, true)); }