コード例 #1
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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));
        }
コード例 #2
0
        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);
                    }
                }
            }
        }
コード例 #3
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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;
                    }
                }
            }
        }
コード例 #4
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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);
        }
コード例 #5
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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);
        }
コード例 #6
0
        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();
                }
            }
        }
コード例 #7
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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);
        }
コード例 #8
0
ファイル: ILModifier.cs プロジェクト: yakumo-proj/Mux
        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);
        }