/// <summary> /// Create app widget provider xml file. /// </summary> private void CreateAppWidgetProviderFile(string tempFolder, int index, CustomAttribute attr) { var resourceName = AppWidgetProviderResource.GetResourceName(index); var path = Path.Combine(Path.Combine(tempFolder, @"res\xml"), resourceName + ".xml"); var doc = new XDocument(); var root = new XElement("appwidget-provider"); doc.Add(root); root.AddAttrIfNotEmpty("minWidth", Namespace, attr.GetValue <string>("MinWidth")); root.AddAttrIfNotEmpty("minHeight", Namespace, attr.GetValue <string>("MinHeight")); root.AddAttrIfNotDefault("updatePeriodMillis", Namespace, attr.GetValue <long>("UpdatePeriod"), 0L); root.AddAttrIfNotEmpty("previewImage", Namespace, attr.GetValue <string>("PreviewImage"), FormatDrawable); root.AddAttrIfNotEmpty("initialLayout", Namespace, attr.GetValue <string>("InitialLayout"), FormatLayout); var configureActivityType = attr.GetValue <TypeReference>("ConfigureActivity"); if (configureActivityType != null) { var configureActivityTypeDef = configureActivityType.Resolve(); if (configureActivityTypeDef == null) { throw new ArgumentException("Cannot resolve " + configureActivityType.FullName); } root.AddAttr("configure", Namespace, FormatClassName(XBuilder.AsTypeDefinition(module, configureActivityTypeDef))); } root.AddAttrIfNotDefault("resizeMode", Namespace, attr.GetValue <int>("ResizeMode"), 0, widgetResizeModesOptions.Format); root.AddAttrIfNotDefault("widgetCategory", Namespace, attr.GetValue <int>("Category"), 0, widgetCategoriesOptions.Format); root.AddAttrIfNotEmpty("initialKeyguardLayout", Namespace, attr.GetValue <string>("InitialKeyguardLayout"), FormatLayout); Directory.CreateDirectory(Path.GetDirectoryName(path)); doc.Save(path); }
/// <summary> /// Create all provider elements /// </summary> private void CreateProvider(XElement manifest) { // Create services foreach (var tuple in FindProviders()) { var type = tuple.Item1; var xType = XBuilder.AsTypeDefinition(module, type); var attr = tuple.Item2; var provider = new XElement("provider"); manifest.Add(provider); provider.AddAttr("name", Namespace, FormatClassName(xType)); var authoritiesArr = (attr != null) ? attr.GetValue <string[]>("Authorities") : null; if (authoritiesArr != null && authoritiesArr.Any()) { //semicolon seperated list provider.AddAttr("authorities", Namespace, string.Join(";", authoritiesArr)); } provider.AddAttrIfFound("enabled", Namespace, attr, "Enabled"); provider.AddAttrIfFound("exported", Namespace, attr, "Exported"); provider.AddAttrIfFound("grantUriPermissions", Namespace, attr, "GrantUriPermissions"); provider.AddAttrIfNotEmpty("icon", Namespace, attr.GetValue <string>("Icon"), FormatDrawable); provider.AddAttrIfNotEmpty("label", Namespace, attr.GetValue <string>("Label"), FormatStringOrLiteral); provider.AddAttrIfFound("multiprocess", Namespace, attr, "MultiProcess"); provider.AddAttrIfNotEmpty("permission", Namespace, attr.GetValue <string>("Permission")); provider.AddAttrIfNotEmpty("process", Namespace, attr.GetValue <string>("Process")); provider.AddAttrIfNotEmpty("readPermission", Namespace, attr.GetValue <string>("ReadPermission")); provider.AddAttrIfFound("syncable", Namespace, attr, "Syncable"); provider.AddAttrIfNotEmpty("writePermission", Namespace, attr.GetValue <string>("WritePermission")); } }
/// <summary> /// Create all service elements /// </summary> private void CreateService(XElement application) { // Create services foreach (var tuple in FindServices()) { var type = tuple.Item1; var xType = XBuilder.AsTypeDefinition(module, type); var attr = tuple.Item2; var service = new XElement("service"); application.Add(service); service.AddAttr("name", Namespace, FormatClassName(xType)); service.AddAttrIfNotEmpty("label", Namespace, attr.GetValue <string>("Label"), FormatStringOrLiteral); service.AddAttrIfNotEmpty("icon", Namespace, attr.GetValue <string>("Icon"), FormatDrawable); service.AddAttrIfFound("enabled", Namespace, attr, "Enabled"); service.AddAttrIfFound("exported", Namespace, attr, "Exporter"); service.AddAttrIfFound("isolatedProcess", Namespace, attr, "IsolatedProcess"); service.AddAttrIfNotEmpty("permission", Namespace, attr.GetValue <string>("Permission")); service.AddAttrIfNotEmpty("process", Namespace, attr.GetValue <string>("Process")); service.AddAttrIfFound("stopWithTask", Namespace, attr, "StopWithTask"); CreateIntentFilter(service, type, false, false); CreateMetaData(service, type); } }
/// <summary> /// Create the application element /// </summary> private void CreateApplication(Targets target, XElement manifest, string outputFolder) { // Find application attribute var appTuple = FindApplication(); var attr = appTuple.Item2; var label = attr.GetValue <string>(0, "Label"); if (string.IsNullOrEmpty(label)) { throw new ArgumentException(string.Format("No Label set in {0}", attr)); } var icon = attr.GetValue <string>("Icon"); if (string.IsNullOrEmpty(icon)) { // Select icon from activity var activityIcons = FindActivities().Select(x => x.Item2.GetValue <string>("Icon")).Where(x => !string.IsNullOrEmpty(x)); icon = activityIcons.FirstOrDefault(); } // Create application var application = new XElement("application"); manifest.Add(application); application.AddAttr("label", Namespace, FormatStringOrLiteral(label)); if (appTuple.Item1 != null) { var xType = XBuilder.AsTypeDefinition(module, appTuple.Item1); application.AddAttr("name", Namespace, FormatClassName(xType)); } application.AddAttrIfNotEmpty("icon", Namespace, icon, FormatDrawable); application.AddAttrIfNotEmpty("theme", Namespace, attr.GetValue <string>("Theme"), FormatStyle); application.AddAttrIfNotEmpty("description", Namespace, attr.GetValue <string>("Description")); application.AddAttrIfNotEmpty("logo", Namespace, attr.GetValue <string>("Logo"), FormatDrawable); application.AddAttrIfNotDefault("debuggable", Namespace, attr.GetValue <bool>("Debuggable", debuggable), false); application.AddAttrIfFound("enabled", Namespace, attr, "Enabled"); application.AddAttrIfNotDefault("persistent", Namespace, attr.GetValue <bool>("Persistent"), false); application.AddAttrIfFound("allowTaskReparenting", Namespace, attr, "AllowTaskReparenting"); application.AddAttrIfNotEmpty("backupAgent", Namespace, attr.GetValue <Type>("BackupAgent"), nsConverter.GetConvertedFullName); application.AddAttrIfFound("hardwareAccelerated", Namespace, attr, "HardwareAccelerated"); application.AddAttrIfFound("killAfterRestore", Namespace, attr, "KillAfterRestore"); application.AddAttrIfFound("largeHeap", Namespace, attr, "LargeHeap"); application.AddAttrIfNotEmpty("manageSpaceActivity", Namespace, attr.GetValue <Type>("ManageSpaceActivity"), nsConverter.GetConvertedFullName); application.AddAttrIfNotEmpty("process", Namespace, attr.GetValue <string>("Process")); application.AddAttrIfFound("restoreAnyVersion", Namespace, attr, "RestoreAnyVersion"); application.AddAttrIfNotEmpty("taskAffinity", Namespace, attr.GetValue <string>("TaskAffinity")); application.AddAttrIfNotDefault("uiOptions", Namespace, attr.GetValue <int>("UIOptions"), 0, uiOptions.Format); // Create child elements CreateActivity(application); CreateService(application); CreateReceiver(application); CreateAppWidgetProvider(application, outputFolder); CreateUsesLibrary(application); CreateProvider(application); CreateMetaData(application, assembly); // Must be last }
/// <summary> /// Gets the type of this variable. /// </summary> protected override TTypeRef GetType <TTypeRef>(ITypeResolver <TTypeRef> typeResolver) { if ((originalVariable == null) || (originalVariable.VariableType == null)) { return(default(TTypeRef)); } var xVarType = XBuilder.AsTypeReference(Type.Module, originalVariable.VariableType); return(typeResolver.GetTypeReference(xVarType)); }
/// <summary> /// Create the current type as class definition. /// </summary> public virtual void Create(ClassDefinition declaringClass, XTypeDefinition declaringType, DexTargetPackage targetPackage) { // Find xfield xField = XBuilder.AsFieldDefinition(compiler.Module, field); // Create field definition dfield = new Dot42.DexLib.FieldDefinition(); dfield.Name = NameConverter.GetConvertedName(field); AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); // Set access flags SetAccessFlags(dfield, field); // Give warning if static in generic class. // This could of cause also be handled automagically be the compiler, // with mixture of whats done in the Interlocked converter and whats // done in the GenericInstanceConverter. if (field.IsStatic && declaringType.IsGenericClass) { if (!field.HasSuppressMessageAttribute("StaticFieldInGenericType") && !field.DeclaringType.HasSuppressMessageAttribute("StaticFieldInGenericType")) { string msg; if (field.Name.Contains("CachedAnonymousMethodDelegate")) { msg = "The compiler generated a static field '{0}' in generic type '{1}'. This is not supported " + "in Dot42 if the anonymous delegate accesses a generic class parameter. A workaround " + "is to convert the anonymous static delegate to a normal method.\n"; } else { msg = "Static field '{0}' in generic type {1}: All generic instances will share " + "the same static field, contrary on how CLR operates. A workaround is to " + "use ConcurrentDictionaries to access the values dependent on the type.\n"; } msg += "You can suppress this warning with a [SuppressMessage(\"dot42\"," + " \"StaticFieldInGenericType\")] attribute, either on the field or on the class."; var body = field.DeclaringType.Methods.Select(m => m.Body) .FirstOrDefault(m => m != null && m.Instructions.Any(i => i.SequencePoint(m) != null)); if (body != null) { var seqPoint = body.Instructions.Select(i => i.SequencePoint(body)).First(i => i != null); DLog.Warning(DContext.CompilerILConverter, seqPoint.Document.Url, seqPoint.StartColumn, seqPoint.StartLine, msg, field.Name, declaringType.FullName); } else { DLog.Warning(DContext.CompilerILConverter, msg, field.Name, declaringType.FullName); } } } }
/// <summary> /// Gets a class reference for the given type reference. /// </summary> internal static TypeReference GetReference(this Mono.Cecil.TypeReference type, DexTargetPackage targetPackage, XModule module) { if (type == null) { throw new ArgumentNullException("type"); } var xType = XBuilder.AsTypeReference(module, type); return(xType.GetReference(targetPackage)); }
/// <summary> /// Gets a Dex method reference for the given type reference. /// </summary> internal static MethodReference GetReference(this Mono.Cecil.MethodReference method, DexTargetPackage targetPackage, XModule module) { if (method == null) { throw new ArgumentNullException("method"); } var xMethod = XBuilder.AsMethodReference(module, method); return(xMethod.GetReference(targetPackage)); }
/// <summary> /// Gets a Dex field reference for the given field reference. /// </summary> internal static FieldReference GetReference(this Mono.Cecil.FieldReference field, DexTargetPackage targetPackage, XModule module) { if (field == null) { throw new ArgumentNullException("field"); } var xField = XBuilder.AsFieldReference(module, field); return(xField.GetReference(targetPackage)); }
/// <summary> /// Gets a class reference for the given type reference. /// </summary> internal static TypeReference GetReference(this JvmClassLib.TypeReference type, XTypeUsageFlags usageFlags, DexTargetPackage targetPackage, XModule module) { if (type == null) { throw new ArgumentNullException("type"); } var xType = XBuilder.AsTypeReference(module, type, usageFlags); return(xType.GetReference(targetPackage)); }
/// <summary> /// Gets all constructors that have to be wrapped in this class. /// </summary> protected virtual IEnumerable <XMethodDefinition> GetBaseClassCtors() { var baseTypeRef = Type.BaseType; var baseType = (baseTypeRef != null) ? baseTypeRef.Resolve() : null; if (baseType == null) { return(Enumerable.Empty <XMethodDefinition>()); } return(baseType.Methods.Where(x => x.IsReachable && !x.IsStatic && x.IsConstructor && !x.IsPrivate) .Select(x => XBuilder.AsMethodDefinition(Compiler.Module, x))); }
/// <summary> /// Create the current type as class definition. /// </summary> public void Create(ClassDefinition declaringClass, DexTargetPackage targetPackage) { // Find xField xField = XBuilder.AsFieldDefinition(compiler.Module, field); // Create field definition dfield = new Dot42.DexLib.FieldDefinition(); dfield.Name = NameConverter.GetConvertedName(field); AddFieldToDeclaringClass(declaringClass, dfield, targetPackage); targetPackage.NameConverter.Record(xField, dfield); // Set access flags SetAccessFlags(dfield, field); }
protected override XTypeDefinition CreateXType(XTypeDefinition parentXType) { var typeDef = (XBuilder.ILTypeDefinition)XBuilder.AsTypeReference(Compiler.Module, Type) .Resolve(); string name = NameConverter.GetNullableClassName(typeDef.Name); XSyntheticTypeFlags xflags = default(XSyntheticTypeFlags); return(XSyntheticTypeDefinition.Create(Compiler.Module, parentXType, xflags, typeDef.Namespace, name, Compiler.Module.TypeSystem.Object, string.Join(":", Type.Scope.Name, Type.MetadataToken.ToScopeId(), "Nullable"))); }
/// <summary> /// Create all activity elements /// </summary> private void CreateActivity(XElement application) { bool isFirst = true; // Create activities foreach (var tuple in FindActivities()) { var type = tuple.Item1; var xType = XBuilder.AsTypeDefinition(module, type); var attr = tuple.Item2; var activity = new XElement("activity"); application.Add(activity); activity.AddAttr("name", Namespace, FormatClassName(xType)); activity.AddAttrIfNotEmpty("label", Namespace, attr.GetValue <string>("Label"), FormatStringOrLiteral); activity.AddAttrIfNotEmpty("icon", Namespace, attr.GetValue <string>("Icon"), FormatDrawable); activity.AddAttrIfFound("allowTaskReparenting", Namespace, attr, "AllowTaskReparenting"); activity.AddAttrIfFound("alwaysRetainTaskState", Namespace, attr, "AlwaysRetainTaskState"); activity.AddAttrIfFound("clearTaskOnLaunch", Namespace, attr, "ClearTaskOnLaunch"); activity.AddAttrIfNotDefault("configChanges", Namespace, attr.GetValue <int>("ConfigChanges"), 0, configChangesOptions.Format); activity.AddAttrIfFound("enabled", Namespace, attr, "Enabled"); activity.AddAttrIfFound("excludeFromRecents", Namespace, attr, "ExcludeFromRecents"); activity.AddAttrIfFound("exported", Namespace, attr, "Exported"); activity.AddAttrIfFound("finishOnTaskLaunch", Namespace, attr, "FinishOnTaskLaunch"); activity.AddAttrIfFound("hardwareAccelerated", Namespace, attr, "HardwareAccelerated"); activity.AddAttrIfNotDefault("launchMode", Namespace, attr.GetValue <int>("LaunchMode"), 0, launchModesOptions.Format); activity.AddAttrIfFound("multiprocess", Namespace, attr, "MultiProcess"); activity.AddAttrIfFound("noHistory", Namespace, attr, "NoHistory"); activity.AddAttrIfNotEmpty("parentActivityName", Namespace, attr.GetValue <Type>("ParentActivity"), nsConverter.GetConvertedFullName); activity.AddAttrIfNotEmpty("permission", Namespace, attr.GetValue <string>("Permission")); activity.AddAttrIfNotEmpty("process", Namespace, attr.GetValue <string>("Process")); activity.AddAttrIfNotDefault("screenOrientation", Namespace, attr.GetValue <int>("ScreenOrientation"), 0, screenOrientationsOptions.Format); activity.AddAttrIfFound("stateNotNeeded", Namespace, attr, "StateNotNeeded"); activity.AddAttrIfNotEmpty("taskAffinity", Namespace, attr.GetValue <string>("TaskAffinity")); activity.AddAttrIfNotEmpty("theme", Namespace, attr.GetValue <string>("Theme"), FormatStyle); activity.AddAttrIfNotDefault("uiOptions", Namespace, attr.GetValue <int>("UIOptions"), 0, uiOptions.Format); activity.AddAttrIfNotDefault("windowSoftInputMode", Namespace, attr.GetValue <int>("WindowSoftInputMode"), 0, windowSoftInputModeOptions.Format); var visibleInLauncher = isFirst || attr.GetValue("VisibleInLauncher", false) || attr.GetValue("MainLauncher", false); CreateIntentFilter(activity, type, visibleInLauncher, false); CreateMetaData(activity, type); isFirst = false; } }
void ConvertParameters(List <ByteCode> body) { AstVariable thisParameter = null; if (methodDef.HasThis) { TypeReference type = methodDef.DeclaringType; thisParameter = new AstILVariable("this", XBuilder.AsTypeReference(module, type.IsValueType ? new ByReferenceType(type) : type), methodDef.Body.ThisParameter); } foreach (var p in methodDef.Parameters) { Parameters.Add(new AstILVariable(p.Name, XBuilder.AsTypeReference(module, p.ParameterType), p)); } if (Parameters.Count > 0 && (methodDef.IsSetter || methodDef.IsAddOn || methodDef.IsRemoveOn)) { // last parameter must be 'value', so rename it Parameters.Last().Name = "value"; } foreach (ByteCode byteCode in body) { ParameterDefinition p; switch (byteCode.Code) { case AstCode.__Ldarg: p = (ParameterDefinition)byteCode.Operand; byteCode.Code = AstCode.Ldloc; byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index]; break; case AstCode.__Starg: p = (ParameterDefinition)byteCode.Operand; byteCode.Code = AstCode.Stloc; byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index]; break; case AstCode.__Ldarga: p = (ParameterDefinition)byteCode.Operand; byteCode.Code = AstCode.Ldloca; byteCode.Operand = p.Index < 0 ? thisParameter : this.Parameters[p.Index]; break; } } if (thisParameter != null) { this.Parameters.Add(thisParameter); } }
/// <summary> /// Create the current type as class definition. /// </summary> public void Create(ClassDefinition declaringClass, DexTargetPackage targetPackage) { // Find xMethod xMethod = XBuilder.AsMethodDefinition(compiler.Module, method); // Create method definition dmethod = new DexLib.MethodDefinition(); dmethod.Name = GetMethodName(method, targetPackage); dmethod.MapFileId = compiler.GetNextMapFileId(); AddMethodToDeclaringClass(declaringClass, dmethod, targetPackage); targetPackage.Record(xMethod, dmethod); // Set access flags SetAccessFlags(dmethod, method); // Create prototype dmethod.Prototype = PrototypeBuilder.BuildPrototype(compiler, targetPackage, declaringClass, xMethod); }
/// <summary> /// Create all activity elements /// </summary> private void CreateAppWidgetProvider(XElement application, string outputFolder) { //Debugger.Launch(); // Create activities var index = -1; foreach (var tuple in FindAppWidgetProviders()) { index++; var type = tuple.Item1; var xType = XBuilder.AsTypeDefinition(module, type); var attr = tuple.Item2; var receiver = new XElement("receiver"); application.Add(receiver); // receiver attributes receiver.AddAttr("name", Namespace, FormatClassName(xType)); receiver.AddAttrIfNotEmpty("label", Namespace, attr.GetValue <string>("Label"), FormatStringOrLiteral); // intent-filter CreateIntentFilter(receiver, type, false, true); // meta-data receiver.Add(new XElement("meta-data", new XAttribute(XName.Get("name", Namespace), "android.appwidget.provider"), new XAttribute(XName.Get("resource", Namespace), "@xml/" + AppWidgetProviderResource.GetResourceName(index)))); CreateMetaData(receiver, type); // Create the appwidget-provider xml file CreateAppWidgetProviderFile(outputFolder, index, attr); } // Check that the number of app widgets is correct if (index > appWidgetProviderCodeFiles.Count) { throw new CompilerException("For more AppWidgetProvider attributes than source files with subtype AppWidgetProvider"); } }
/// <summary> /// Implement the class now that all classes have been created /// </summary> protected override void CreateMembers(DexTargetPackage targetPackage) { // Build ctors foreach (var baseCtor in GetBaseClassCtors()) { // Build ctor var prototype = PrototypeBuilder.BuildPrototype(Compiler, targetPackage, null, baseCtor); var ctor = new MethodDefinition(Class, "<init>", prototype); ctor.AccessFlags = AccessFlags.Public | AccessFlags.Constructor; Class.Methods.Add(ctor); // Create ctor body var ctorBody = CreateCtorBody(prototype); targetPackage.Record(new CompiledMethod { DexMethod = ctor, RLBody = ctorBody }); } // build original type field // Create field definition var dfield = new Dot42.DexLib.FieldDefinition(); dfield.Owner = Class; dfield.Name = "underlying$"; dfield.IsSynthetic = true; dfield.IsFinal = true; dfield.IsStatic = true; dfield.IsPublic = true; dfield.Type = Compiler.Module.TypeSystem.Type.GetClassReference(targetPackage); // not sure if GetClassReference is the best way to go forward here. // might depend on the sort order of the class builders. var underlyingType = XBuilder.AsTypeReference(Compiler.Module, Type); dfield.Value = underlyingType.GetClassReference(targetPackage); Class.Fields.Add(dfield); }
/// <summary> /// Create all receiver elements /// </summary> private void CreateReceiver(XElement application) { // Create receivers foreach (var tuple in FindReceivers()) { var type = tuple.Item1; var xType = XBuilder.AsTypeDefinition(module, type); var attr = tuple.Item2; var receiver = new XElement("receiver"); application.Add(receiver); receiver.AddAttr("name", Namespace, FormatClassName(xType)); receiver.AddAttrIfNotEmpty("label", Namespace, attr.GetValue <string>("Label"), FormatStringOrLiteral); receiver.AddAttrIfNotEmpty("icon", Namespace, attr.GetValue <string>("Icon"), FormatDrawable); receiver.AddAttrIfFound("enabled", Namespace, attr, "Enabled"); receiver.AddAttrIfFound("exported", Namespace, attr, "Exported"); receiver.AddAttrIfNotEmpty("permission", Namespace, attr.GetValue <string>("Permission")); receiver.AddAttrIfNotEmpty("process", Namespace, attr.GetValue <string>("Process")); CreateIntentFilter(receiver, type, false, false); CreateMetaData(receiver, type); } }
/// <summary> /// Create all annotations for this method /// </summary> internal virtual void CreateAnnotations(DexTargetPackage targetPackage) { // Build method annotations AttributeAnnotationInstanceBuilder.CreateAttributeAnnotations(compiler, method, dmethod, targetPackage); // only add generics annotation for getters or setters or constructors if (method.IsGetter) { // Note that the return type might has been // changed above, to compensate for interface // inheritance and generic specialization. // We need to use the original declaration. // TODO: why not get rid of "OriginalReturnType" // and use the IL's return type?? var returnType = xMethod.OriginalReturnType; var xType = XBuilder.AsTypeReference(compiler.Module, returnType); dmethod.AddGenericDefinitionAnnotationIfGeneric(xType, compiler, targetPackage); } else if (method.IsSetter) { for (int i = 0; i < xMethod.Parameters.Count; ++i) { var dp = dmethod.Prototype.Parameters[i]; dp.AddGenericDefinitionAnnotationIfGeneric(xMethod.Parameters[i].ParameterType, compiler, targetPackage); } } else if (method.IsConstructor && !method.IsStatic) { // Add parameter names and original access flags, as these might be important // in serialization and/or dependency injection. var reflectionInfo = compiler.GetDot42InternalType(InternalConstants.ReflectionInfoAnnotation) .GetClassReference(targetPackage); var annotation = new Annotation { Type = reflectionInfo, Visibility = AnnotationVisibility.Runtime }; bool isPublic = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; // Not sure if it makes any sense to remap the access flags. bool isProtected = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family || (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem || (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; bool isInternal = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly || (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem || (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; bool isPrivate = (method.OriginalAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; // only create accessFlags if they differs from java's if (isPublic != dmethod.IsPublic || isProtected != dmethod.IsProtected || isPrivate != dmethod.IsPrivate || isInternal) { int accessFlags = 0; if (isPublic) { accessFlags |= 0x01; } if (isProtected) { accessFlags |= 0x02; } if (isPrivate) { accessFlags |= 0x04; } if (isInternal) { accessFlags |= 0x08; } annotation.Arguments.Add(new AnnotationArgument(InternalConstants.ReflectionInfoAccessFlagsField, accessFlags)); } if (method.Parameters.Count > 0) { annotation.Arguments.Add(new AnnotationArgument(InternalConstants.ReflectionInfoParameterNamesField, method.Parameters.Select(p => p.Name).ToArray())); } if (annotation.Arguments.Count > 0) { dmethod.Annotations.Add(annotation); } //for (int i = 0; i < xMethod.Parameters.Count; ++i) //{ // var dp = dmethod.Prototype.Parameters[i]; // dp.AddGenericDefinitionAnnotationIfGeneric(xMethod.Parameters[i].ParameterType, compiler, // targetPackage); //} } }
private static MethodDefinition CreateFactoryMethod(AssemblyCompiler compiler, DexTargetPackage targetPackage, CustomAttribute attribute, AttributeAnnotationMapping mapping) { var targetClass = mapping.AttributeClass; // is this really the right place for the factory methods? ISourceLocation seqp = null; var attributeTypeDef = attribute.AttributeType.Resolve(); // create method string methodName = CreateAttributeFactoryMethodName(targetClass); MethodDefinition method = new MethodDefinition(targetClass, methodName, new Prototype(mapping.AttributeClass)); method.AccessFlags = AccessFlags.Public | AccessFlags.Static | AccessFlags.Synthetic; targetClass.Methods.Add(method); // create method body MethodBody body = new MethodBody(null); // Allocate attribute Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object); body.Instructions.Add(seqp, RCode.New_instance, mapping.AttributeClass, attributeReg); // collect ctor arguments List <Register> ctorArgRegs = new List <Register>() { attributeReg }; foreach (var p in attribute.ConstructorArguments) { XTypeReference xType = XBuilder.AsTypeReference(compiler.Module, p.Type); Register[] valueRegs = CreateInitializeValueInstructions(seqp, body, xType, p, compiler, targetPackage); ctorArgRegs.AddRange(valueRegs); } // Invoke ctor DexLib.MethodReference dctor = attribute.Constructor.GetReference(targetPackage, compiler.Module); body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, ctorArgRegs.ToArray()); // set field values foreach (var p in attribute.Fields) { var field = GetField(attributeTypeDef, p.Name); var xField = XBuilder.AsFieldReference(compiler.Module, field); Register[] valueRegs = CreateInitializeValueInstructions(seqp, body, xField.FieldType, p.Argument, compiler, targetPackage); body.Instructions.Add(seqp, xField.FieldType.IPut(), xField.GetReference(targetPackage), valueRegs[0], attributeReg); } // set property values foreach (var p in attribute.Properties) { PropertyDefinition property = GetSettableProperty(attributeTypeDef, p.Name); XTypeReference xType = XBuilder.AsTypeReference(compiler.Module, property.PropertyType); Register[] valueRegs = CreateInitializeValueInstructions(seqp, body, xType, p.Argument, compiler, targetPackage); XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod); body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null), xSetMethod.GetReference(targetPackage), new[] { attributeReg }.Concat(valueRegs).ToArray()); } // Return attribute body.Instructions.Add(seqp, RCode.Return_object, attributeReg); // Register method body targetPackage.Record(new CompiledMethod() { DexMethod = method, RLBody = body }); // Return method return(method); }
/// <summary> /// Make a xtype reference for a java class name. /// </summary> private XTypeReference AsTypeReference(string className, XTypeUsageFlags usageFlags) { return(XBuilder.AsTypeReference(module, className, usageFlags)); }
/// <summary> /// Make a .NET type reference for a java type reference. /// </summary> private XTypeReference AsTypeReference(JvmClassLib.TypeReference javaRef, XTypeUsageFlags usageFlags) { return(XBuilder.AsTypeReference(module, javaRef, usageFlags)); }
/// <summary> /// Make a .NET type reference for a java class file. /// </summary> private XTypeReference AsTypeReference(ClassFile classFile, XTypeUsageFlags usageFlags) { return(XBuilder.AsTypeReference(module, classFile, usageFlags)); }
/// <summary> /// Create a method definition for the builder method that builds a custom attribute from an annotation. /// </summary> private static MethodDefinition CreateBuildMethod( ISourceLocation seqp, Mono.Cecil.MethodDefinition ctor, List <MethodDefinition> paramGetMethods, AssemblyCompiler compiler, DexTargetPackage targetPackage, ClassDefinition attributeClass, AttributeAnnotationInterface mapping) { // Create method definition string name = CreateBuildMethodName(attributeClass); TypeReference attributeTypeRef = ctor.DeclaringType.GetReference(targetPackage, compiler.Module); MethodDefinition method = new MethodDefinition(attributeClass, name, new Prototype(attributeTypeRef, new Parameter(mapping.AnnotationInterfaceClass, "ann"))); method.AccessFlags = AccessFlags.Public | AccessFlags.Static | AccessFlags.Synthetic; attributeClass.Methods.Add(method); // Create method body MethodBody body = new MethodBody(null); Register annotationReg = body.AllocateRegister(RCategory.Argument, RType.Object); //body.Instructions.Add(seqp, RCode.Check_cast, mapping.AnnotationInterfaceClass, annotationReg); // Allocate attribute Register attributeReg = body.AllocateRegister(RCategory.Temp, RType.Object); body.Instructions.Add(seqp, RCode.New_instance, attributeClass, attributeReg); // Get ctor arguments List <Register> ctorArgRegs = new List <Register>(); foreach (MethodDefinition p in paramGetMethods) { TypeReference paramType = p.Prototype.ReturnType; Register[] valueRegs = CreateLoadValueSequence(seqp, body, paramType, annotationReg, p); ctorArgRegs.AddRange(valueRegs); } // Invoke ctor DexLib.MethodReference dctor = ctor.GetReference(targetPackage, compiler.Module); body.Instructions.Add(seqp, RCode.Invoke_direct, dctor, new[] { attributeReg }.Concat(ctorArgRegs).ToArray()); // Get field values foreach (var fieldMap in mapping.FieldToGetMethodMap) { Mono.Cecil.FieldDefinition field = fieldMap.Key; MethodDefinition getter = fieldMap.Value; Register[] valueRegs = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter); DexLib.FieldReference dfield = field.GetReference(targetPackage, compiler.Module); XModel.XTypeReference xFieldType = XBuilder.AsTypeReference(compiler.Module, field.FieldType); body.Instructions.Add(seqp, xFieldType.IPut(), dfield, valueRegs[0], attributeReg); } // Get property values foreach (var propertyMap in mapping.PropertyToGetMethodMap) { PropertyDefinition property = propertyMap.Key; MethodDefinition getter = propertyMap.Value; Register[] valueRegs = CreateLoadValueSequence(seqp, body, getter.Prototype.ReturnType, annotationReg, getter); DexLib.MethodReference dmethod = property.SetMethod.GetReference(targetPackage, compiler.Module); XModel.XMethodDefinition xSetMethod = XBuilder.AsMethodDefinition(compiler.Module, property.SetMethod); body.Instructions.Add(seqp, xSetMethod.Invoke(xSetMethod, null), dmethod, new[] { attributeReg }.Concat(valueRegs).ToArray()); } // Return attribute body.Instructions.Add(seqp, RCode.Return_object, attributeReg); // Register method body targetPackage.Record(new CompiledMethod() { DexMethod = method, RLBody = body }); // Return method return(method); }
/// <summary> /// Create code to initialize a value from an attribute. /// </summary> /// <returns>The register(s) holding the value</returns> private static Register[] CreateInitializeValueInstructions(ISourceLocation seqp, MethodBody body, XTypeReference targetType, CustomAttributeArgument value, AssemblyCompiler compiler, DexTargetPackage targetPackage) { List <Register> result = new List <Register>(); // allocate result, initialize to default value. if (targetType.IsWide()) { Tuple <Register, Register> regs = body.AllocateWideRegister(RCategory.Temp); //body.Instructions.Add(seqp, RCode.Const_wide, 0, regs.Item1); result.Add(regs.Item1); result.Add(regs.Item2); } else if (targetType.IsPrimitive) { Register reg = body.AllocateRegister(RCategory.Temp, RType.Value); //body.Instructions.Add(seqp, RCode.Const, 0, reg); result.Add(reg); } else // object { Register reg = body.AllocateRegister(RCategory.Temp, RType.Object); //body.Instructions.Add(seqp, RCode.Const, 0, reg); result.Add(reg); } // load data if (value.Value == null) // must be a reference type { body.Instructions.Add(seqp, RCode.Const, 0, result[0]); body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]); return(result.ToArray()); } var valueType = XBuilder.AsTypeReference(compiler.Module, value.Type); if (value.Value is CustomAttributeArgument) { // this happens if a type conversion is neccessary var nestedValue = (CustomAttributeArgument)value.Value; valueType = XBuilder.AsTypeReference(compiler.Module, nestedValue.Type); var rOrigValue = CreateInitializeValueInstructions(seqp, body, valueType, nestedValue, compiler, targetPackage); if (!nestedValue.Type.IsPrimitive) { body.Instructions.Add(seqp, RCode.Move_object, result[0], rOrigValue[0]); body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]); } else if (!targetType.IsPrimitive) { body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rOrigValue); body.Instructions.Add(seqp, RCode.Move_result_object, result[0]); body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]); } else { throw new Exception(string.Format("type converstion in attribute {0}=>{1} not yet supported", valueType.FullName, targetType.FullName)); } } else if (valueType.IsArray) { var array = (CustomAttributeArgument[])value.Value; var elementType = valueType.ElementType; Register rIndex = body.AllocateRegister(RCategory.Temp, RType.Value); body.Instructions.Add(seqp, RCode.Const, array.Length, rIndex); body.Instructions.Add(seqp, RCode.New_array, valueType.GetReference(targetPackage), result[0], rIndex); // iterate through each value for (int i = 0; i < array.Length; i++) { Register rLoaded = CreateInitializeValueInstructions(seqp, body, elementType, array[i], compiler, targetPackage)[0]; body.Instructions.Add(seqp, RCode.Const, i, rIndex); body.Instructions.Add(seqp, valueType.APut(), rLoaded, result[0], rIndex); } } else if (targetType.IsEnum()) { var enumClass = (targetType.IsEnum()? targetType:valueType).GetReference(targetPackage); Register rEnumClass = body.AllocateRegister(RCategory.Temp, RType.Object); body.Instructions.Add(seqp, RCode.Const_class, enumClass, rEnumClass); long lVal = Convert.ToInt64(value.Value); if (lVal <= int.MaxValue && lVal >= int.MinValue) { Register regTmp = body.AllocateRegister(RCategory.Temp, RType.Value); body.Instructions.Add(seqp, RCode.Const, (int)lVal, regTmp); var get = compiler.GetDot42InternalType("Enum").Resolve() .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && !p.Parameters[1].ParameterType.IsWide()) .GetReference(targetPackage); body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp); body.Instructions.Add(seqp, targetType.MoveResult(), result[0]); } else { var regTmp = body.AllocateWideRegister(RCategory.Temp); body.Instructions.Add(seqp, RCode.Const, (long)lVal, regTmp.Item1); var get = compiler.GetDot42InternalType("Enum").Resolve() .Methods.Single(p => p.Name == "Get" && p.Parameters.Count == 2 && p.Parameters[1].ParameterType.IsWide()) .GetReference(targetPackage); body.Instructions.Add(seqp, RCode.Invoke_static, get, rEnumClass, regTmp.Item1); body.Instructions.Add(seqp, targetType.MoveResult(), result[0]); } body.Instructions.Add(seqp, RCode.Check_cast, targetType.GetReference(targetPackage), result[0]); } else if (valueType.IsSystemString()) { body.Instructions.Add(seqp, RCode.Const_string, (string)value.Value, result[0]); } else if (valueType.IsSystemType()) { var type = XBuilder.AsTypeReference(compiler.Module, (TypeReference)value.Value); // TODO: this might not work with typeof(void) on ART runtime. body.Instructions.Add(seqp, RCode.Const_class, type.GetReference(targetPackage), result[0]); } else if (!valueType.IsPrimitive) { // can this happen? throw new Exception("invalid value type in attribute: " + targetType.FullName); } else { if (targetType.IsSystemObject()) { // can this happen? or is this always handled above? // boxing required. var rUnboxed = CreateInitializeValueInstructions(seqp, body, valueType, value, compiler, targetPackage); body.Instructions.Add(seqp, RCode.Invoke_static, valueType.GetBoxValueOfMethod(), rUnboxed); body.Instructions.Add(seqp, RCode.Move_result_object, result[0]); } else if (targetType.IsDouble()) { body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToDouble(value.Value), result[0]); } else if (targetType.IsWide() && valueType.IsUInt64()) { body.Instructions.Add(seqp, RCode.Const_wide, (long)Convert.ToUInt64(value.Value), result[0]); } else if (targetType.IsWide()) { body.Instructions.Add(seqp, RCode.Const_wide, Convert.ToInt64(value.Value), result[0]); } else if (targetType.IsFloat()) { body.Instructions.Add(seqp, RCode.Const, Convert.ToSingle(value.Value), result[0]); } else { body.Instructions.Add(seqp, RCode.Const, (int)Convert.ToInt64(value.Value), result[0]); } } return(result.ToArray()); }
/// <summary> /// Convert the given interface method if it has explicit implementations. /// </summary> private void ConvertInterfaceMethod(TypeDefinition iType, MethodDefinition iMethod) { var implementations = GetImplementations(iMethod); var iMethodIsJavaWithGenericParams = iMethod.IsJavaMethodWithGenericParams(); var iMethodContainsGenericParams = iMethod.ContainsGenericParameter; if (!iMethodIsJavaWithGenericParams && !iMethodContainsGenericParams && (!implementations.Any(x => x.IsExplicitImplementation()))) { // There are no explicit implementation. // No need to convert return; } // Rename method string newName; bool createExplicitStubs = true; var oldName = iMethod.Name; var attr = iMethod.GetDexOrJavaImportAttribute(); if (attr != null) { string className; string memberName; string descriptor; attr.GetDexOrJavaImportNames(iMethod, out memberName, out descriptor, out className); newName = memberName; } else if ((attr = iMethod.GetDexNameAttribute()) != null) { newName = (string)(attr.ConstructorArguments[0].Value); createExplicitStubs = false; } else { var module = reachableContext.Compiler.Module; var xiType = XBuilder.AsTypeReference(module, iType); newName = methodNames.GetUniqueName(NameConverter.GetConvertedName(xiType) + "_" + iMethod.Name); oldName = newName; } Rename(iMethod, newName); // Update implementations foreach (var impl in implementations) { if (impl.IsExplicitImplementation()) { // Convert to implicit impl.IsPublic = true; // Rename Rename(impl, newName); // Update names of overrides foreach (var @override in impl.Overrides) { @override.Name = newName; } } else if (!(impl.HasDexImportAttribute() || impl.HasJavaImportAttribute())) { // Add stub redirecting explicit implementation to implicit implementation if (createExplicitStubs) { CreateExplicitStub(impl, newName, oldName, iMethod, iMethodIsJavaWithGenericParams /*|| iMethodContainsGenericParams*/); } } } }
/// <summary> /// Make a .NET field reference from a java constant pool method reference. /// </summary> private XFieldReference AsFieldReference(ConstantPoolFieldRef cpField) { return(XBuilder.AsFieldReference(module, cpField)); }
/// <summary> /// Make a .NET method reference from a java constant pool method reference. /// </summary> private XMethodReference AsMethodReference(ConstantPoolMethodRef cpMethod, bool hasThis) { return(XBuilder.AsMethodReference(module, cpMethod, hasThis)); }
/// <summary> /// Create the XType for this builder. /// </summary> protected virtual XTypeDefinition CreateXType(XTypeDefinition parentXType) { return(XBuilder.AsTypeReference(compiler.Module, typeDef).Resolve()); }