private static bool ShouldRecompile(ILXamarin xamarin, Type type, TypeDefinition ilType, IEnumerable <string> sources) { foreach (var nestedIlType in ilType.NestedTypes) { Type nestedType; var nestedSlot = new Slot { muxNamespace = nestedIlType.Namespace, muxName = nestedIlType.Name }; if (type.nested.TryGetValue(nestedSlot, out nestedType) && ShouldRecompile(xamarin, nestedType, nestedIlType, sources)) { return(true); } } if (type.asset == null || (sources != null && !sources.Contains(type.asset))) { return(false); } var initializer = FindInitializeComponent(ilType); if (initializer == null) { return(false); } return(Validate(FindXamlResourceIdAttribute(xamarin, ilType), initializer)); }
public void Recompile(IEnumerable <UnityEditor.Compilation.Assembly> lockedAssemblies, IEnumerable <string> sources) { using (var resolver = new Resolver()) { var xamarin = new ILXamarin(resolver); foreach (var assembly in lockedAssemblies) { using (var definition = AssemblyDefinition.ReadAssembly(assembly.outputPath)) { var modifier = new ILModifier(assembly, definition); modifier.Recompile(xamarin, _types, sources); } } } }
public void Recompile(ILXamarin xamarin, Dictionary <Slot, Type> types, IEnumerable <string> sources) { foreach (var module in definition.Modules) { foreach (var type in types) { var ilType = module.GetType(type.Key.muxNamespace, type.Key.muxName); if (ilType != null && ShouldRecompile(xamarin, type.Value, ilType, sources)) { AssetDatabase.ImportAsset(compilation.sourceFiles[0], ImportAssetOptions.ForceUpdate); return; } } } }
public bool Modify(ILXamarin xamarin, Dictionary <Slot, Type> types, IEnumerable <string> sources) { var modified = false; var assemblyIsToCompile = IsToCompile(true, definition); foreach (var module in definition.Modules) { var moduleIsToCompile = IsToCompile(assemblyIsToCompile, module); foreach (var type in types.ToArray()) { var ilType = module.GetType(type.Key.muxNamespace, type.Key.muxName); if (ilType != null && Modify(xamarin, types, type.Key, type.Value, ilType, moduleIsToCompile, sources)) { modified = true; } } } return(modified); }
private static CustomAttribute FindXamlResourceIdAttribute(ILXamarin xamarin, TypeDefinition type) { var stringType = type.Module.TypeSystem.String; var typeType = new TypeReference("System", "Type", type.Module, type.Module.TypeSystem.CoreLibrary); var voidType = type.Module.TypeSystem.Void; foreach (var attribute in type.Module.Assembly.CustomAttributes) { if ( FullNameEquals(attribute.AttributeType, xamarin.xamlResourceIdAttribute.DeclaringType) && attribute.Constructor.Parameters.Count == 3 && FullNameEquals(attribute.Constructor.Parameters[0].ParameterType, stringType) && FullNameEquals(attribute.Constructor.Parameters[1].ParameterType, stringType) && FullNameEquals(attribute.Constructor.Parameters[2].ParameterType, typeType) && attribute.ConstructorArguments.Count == 3 && FullNameEquals(attribute.ConstructorArguments[2].Type, typeType) && FullNameEquals((TypeReference)attribute.ConstructorArguments[2].Value, type)) { return(attribute); } } return(null); }
public void Modify(IEnumerable <UnityEditor.Compilation.Assembly> lockedAssemblies, IEnumerable <string> sources = null) { var modifiers = new List <ILModifier>(); EditorApplication.LockReloadAssemblies(); try { using (var resolver = new Resolver()) { var xamarin = new ILXamarin(resolver); foreach (var assembly in lockedAssemblies) { var definition = resolver.Add(assembly.outputPath, true); if (definition != null) { modifiers.Add(new ILModifier(assembly, definition)); } } var engine = new Build.BuildEngine(); var logger = new Build.Logger(); logger.Verbosity = Settings.Verbosity; logger.Initialize(engine); while (modifiers.Count > 0) { var modifier = modifiers.Last(); try { foreach (var reference in modifier.compilation.allReferences) { resolver.Add(reference, false); } var modified = modifier.Modify(xamarin, _types, sources); if (modified) { modifier.Write(); } if (modified) { resolver.DisposeAssembly(modifier.compilation.outputPath, modifier.definition); var task = new XamlCTask(); task.BuildEngine = engine; task.Assembly = modifier.compilation.outputPath; task.DebugSymbols = Settings.DebugSymbols.value; task.DebugType = "portable"; task.OptimizeIL = Settings.OptimizeIL.value; task.CompileByDefault = true; task.DefaultAssemblyResolver = resolver; engine.ProjectFileOfTaskNode = task.Assembly; task.Execute(); } } catch (Exception exception) { Debug.LogException(exception); } finally { modifiers.RemoveAt(modifiers.Count - 1); modifier.Dispose(); } } } } finally { EditorApplication.UnlockReloadAssemblies(); foreach (var modifier in modifiers) { modifier.Dispose(); } } }
private static void FillInitializeComponent(MethodDefinition initializer, Type type, TypeReference typeType, ILXamarin xamarin) { var module = initializer.Module; var runtimeTypeHandle = new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.CoreLibrary); runtimeTypeHandle.IsValueType = true; var getTypeFromHandle = new MethodReference("GetTypeFromHandle", typeType, typeType); getTypeFromHandle.Parameters.Add(new ParameterDefinition(runtimeTypeHandle)); var loadFromXamlInstance = new GenericInstanceMethod(xamarin.loadFromXaml); loadFromXamlInstance.GenericArguments.Add(initializer.DeclaringType); var fields = new List <FieldDefinition>(); TypeReference baseType = initializer.DeclaringType; while (baseType != null) { if (baseType.Namespace == "Xamarin.Forms" && baseType.Name == "BindableObject") { foreach (var name in type.names) { foreach (var field in initializer.DeclaringType.Fields) { if (field.Name == name) { fields.Add(field); break; } } } break; } baseType = baseType.Resolve().BaseType; } initializer.Body = new MethodBody(initializer); var il = initializer.Body.GetILProcessor(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldtoken, initializer.DeclaringType); il.Emit(OpCodes.Call, module.ImportReference(getTypeFromHandle)); il.Emit(OpCodes.Call, module.ImportReference(loadFromXamlInstance)); if (fields.Count > 0) { var getNameScope = module.ImportReference(xamarin.getNameScope); var iNameScope = module.ImportReference(xamarin.getNameScope.ReturnType); var findByName = module.ImportReference(xamarin.findByName); var loc = new VariableDefinition(iNameScope); initializer.Body.Variables.Add(loc); il.Emit(OpCodes.Call, getNameScope); il.Emit(OpCodes.Stloc_0); foreach (var field in fields) { var fieldType = field.FieldType; il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldstr, field.Name); il.Emit(OpCodes.Callvirt, findByName); if (fieldType.Namespace != "System" || fieldType.Name != "Object") { il.Emit(fieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, fieldType); } il.Emit(OpCodes.Stfld, field); } } else { il.Emit(OpCodes.Pop); } il.Emit(OpCodes.Ret); }
private bool Modify(ILXamarin xamarin, Dictionary <Slot, Type> siblings, Slot slot, Type type, TypeDefinition ilType, bool compile, IEnumerable <string> sources) { var modified = false; foreach (var nestedIlType in ilType.NestedTypes) { Type nestedType; var nestedSlot = new Slot { muxNamespace = nestedIlType.Namespace, muxName = nestedIlType.Name }; if (type.nested.TryGetValue(nestedSlot, out nestedType) && Modify(xamarin, type.nested, nestedSlot, nestedType, nestedIlType, compile, sources)) { modified = true; } } if (type.asset == null || (sources != null && !sources.Contains(type.asset))) { return(modified); } var initializer = FindInitializeComponent(ilType); if (initializer == null) { return(modified); } compile = IsToCompile(compile, ilType); var stringType = ilType.Module.TypeSystem.String; var typeType = new TypeReference("System", "Type", ilType.Module, ilType.Module.TypeSystem.CoreLibrary); var voidType = ilType.Module.TypeSystem.Void; var attribute = FindXamlResourceIdAttribute(xamarin, ilType); if (!Validate(attribute, initializer)) { return(modified); } try { UpdateOrAddResource(ilType.Module.Resources, type); } catch (DirectoryNotFoundException) { goto NotFound; } catch (FileNotFoundException) { goto NotFound; } if (compile) { initializer = ilType.Methods.FirstOrDefault(method => method.Name == "__InitComponentRuntime"); } if (initializer == null) { initializer = new MethodDefinition("__InitComponentRuntime", MethodAttributes.Private, voidType); ilType.Methods.Add(initializer); FillInitializeComponent(initializer, type, typeType, xamarin); modified = true; } if (attribute == null) { attribute = new CustomAttribute(ilType.Module.ImportReference(xamarin.xamlResourceIdAttribute)); ilType.Module.Assembly.CustomAttributes.Add(attribute); FillXamlResourceIdAttributeArguments(attribute.ConstructorArguments, type, ilType, stringType, typeType); modified = true; } return(modified); NotFound: if (type.nested.Count > 0) { type.asset = null; siblings[slot] = type; } else { siblings.Remove(slot); } return(modified); }