public override bool Execute(out IList <Exception> thrownExceptions) { thrownExceptions = null; LoggingHelper.LogMessage(Normal, $"{new string(' ', 0)}Preparing debug code for xamlc, assembly: {Assembly}"); var resolver = new DefaultAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {dep}"); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = IOPath.GetDirectoryName(p); LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {searchpath}"); resolver.AddSearchDirectory(searchpath); } } var debug = DebugSymbols || (!string.IsNullOrEmpty(DebugType) && DebugType.ToLowerInvariant() != "none"); using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly, new ReaderParameters { ReadWrite = true, ReadSymbols = debug, AssemblyResolver = resolver })) { foreach (var module in assemblyDefinition.Modules) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Module: {module.Name}"); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); if (!resource.IsXaml(module, out var classname)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}no type found... skipped."); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}no InitializeComponent found... skipped."); continue; } var initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime"); if (initCompRuntime == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Creating empty {typeDef.Name}.__InitComponentRuntime"); initCompRuntime = new MethodDefinition("__InitComponentRuntime", initComp.Attributes, initComp.ReturnType); initCompRuntime.Body.InitLocals = true; LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Copying body of InitializeComponent to __InitComponentRuntime"); initCompRuntime.Body = new MethodBody(initCompRuntime); var iCRIl = initCompRuntime.Body.GetILProcessor(); foreach (var instr in initComp.Body.Instructions) { iCRIl.Append(instr); } initComp.Body.Instructions.Clear(); initComp.Body.GetILProcessor().Emit(OpCodes.Ret); typeDef.Methods.Add(initCompRuntime); LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } // IL_0000: ldarg.0 // IL_0001: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.ContentPage::'.ctor'() // // IL_0006: nop // IL_0007: ldarg.1 // IL_0008: brfalse IL_0018 // // IL_000d: ldarg.0 // IL_000e: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitializeComponent() // IL_0013: br IL_001e // // IL_0018: ldarg.0 // IL_0019: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::__InitComponentRuntime() // IL_001e: ret var altCtor = typeDef.Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType == module.TypeSystem.Boolean); if (altCtor != null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing body of {typeDef.Name}.{typeDef.Name} (bool {altCtor.Parameters[0].Name})"); } else { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Adding {typeDef.Name}.{typeDef.Name} (bool useCompiledXaml)"); altCtor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, module.TypeSystem.Void); altCtor.Parameters.Add(new ParameterDefinition("useCompiledXaml", ParameterAttributes.None, module.TypeSystem.Boolean)); } var body = new MethodBody(altCtor) { InitLocals = true }; var il = body.GetILProcessor(); var br2 = Instruction.Create(OpCodes.Ldarg_0); var ret = Instruction.Create(OpCodes.Ret); il.Emit(OpCodes.Ldarg_0); MethodReference baseCtor; if (typeDef.BaseType.Resolve().GetConstructors().FirstOrDefault(c => c.HasParameters && c.Parameters.Count == 1 && c.Parameters[0].Name == "useCompiledXaml") is MethodDefinition baseCtorDef) { baseCtor = module.ImportReference(baseCtorDef); baseCtor = module.ImportReference(baseCtor.ResolveGenericParameters(typeDef.BaseType, module)); il.Emit(OpCodes.Ldarg_1); } else { baseCtor = module.ImportReference(typeDef.BaseType.Resolve().GetConstructors().First(c => c.HasParameters == false)); baseCtor = module.ImportReference(baseCtor.ResolveGenericParameters(typeDef.BaseType, module)); } il.Emit(OpCodes.Callvirt, baseCtor); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Brfalse, br2); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, initComp); il.Emit(OpCodes.Br, ret); il.Append(br2); il.Emit(OpCodes.Callvirt, initCompRuntime); il.Append(ret); altCtor.Body = body; if (!typeDef.Methods.Contains(altCtor)) { typeDef.Methods.Add(altCtor); } LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } } LoggingHelper.LogMessage(Normal, $"{new string(' ', 0)}Writing the assembly."); assemblyDefinition.Write(new WriterParameters { WriteSymbols = debug }); } LoggingHelper.LogMessage(Normal, $"{new string(' ', 2)}done."); return(true); }
public override bool Execute(out IList <Exception> thrownExceptions) { thrownExceptions = null; Logger = Logger ?? new Logger(null, Verbosity); Logger.LogLine(1, "Compiling Xaml"); Logger.LogLine(1, "\nAssembly: {0}", Assembly); if (!string.IsNullOrEmpty(DependencyPaths)) { Logger.LogLine(1, "DependencyPaths: \t{0}", DependencyPaths); } if (!string.IsNullOrEmpty(ReferencePath)) { Logger.LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/")); } Logger.LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols); Logger.LogLine(3, "DebugType:\"{0}\"", DebugType); var skipassembly = true; //change this to false to enable XamlC by default bool success = true; if (!File.Exists(Assembly)) { Logger.LogLine(1, "Assembly file not found. Skipping XamlC."); return(true); } var resolver = new XamlCAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { Logger.LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); Logger.LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); } } var debug = DebugSymbols || (!string.IsNullOrEmpty(DebugType) && DebugType.ToLowerInvariant() != "none"); var readerParameters = new ReaderParameters { AssemblyResolver = resolver, ReadWrite = !ReadOnly, ReadSymbols = debug, }; using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), readerParameters)) { CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } Logger.LogLine(2, " Module: {0}", module.Name); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { Logger.LogString(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { Logger.LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { Logger.LogLine(2, "no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (Type != null) { skiptype = !(Type == classname); } if (skiptype) { Logger.LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { Logger.LogLine(2, "no InitializeComponent found... skipped."); continue; } Logger.LogLine(2, ""); CustomAttribute xamlFilePathAttr; var xamlFilePath = typeDef.HasCustomAttributes && (xamlFilePathAttr = typeDef.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlFilePathAttribute")) != null ? (string)xamlFilePathAttr.ConstructorArguments[0].Value : resource.Name; var initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime"); if (initCompRuntime != null) { Logger.LogLine(2, " __InitComponentRuntime already exists... not creating"); } else { Logger.LogString(2, " Creating empty {0}.__InitComponentRuntime ...", typeDef.Name); initCompRuntime = new MethodDefinition("__InitComponentRuntime", initComp.Attributes, initComp.ReturnType); initCompRuntime.Body.InitLocals = true; Logger.LogLine(2, "done."); Logger.LogString(2, " Copying body of InitializeComponent to __InitComponentRuntime ...", typeDef.Name); initCompRuntime.Body = new MethodBody(initCompRuntime); var iCRIl = initCompRuntime.Body.GetILProcessor(); foreach (var instr in initComp.Body.Instructions) { iCRIl.Append(instr); } initComp.Body.Instructions.Clear(); initComp.Body.GetILProcessor().Emit(OpCodes.Ret); initComp.Body.InitLocals = true; typeDef.Methods.Add(initCompRuntime); Logger.LogLine(2, "done."); } Logger.LogString(2, " Parsing Xaml... "); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { Logger.LogLine(2, "failed."); continue; } Logger.LogLine(2, "done."); hasCompiledXamlResources = true; Logger.LogString(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); Exception e; if (!TryCoreCompile(initComp, initCompRuntime, rootnode, resource.Name, out e)) { success = false; Logger.LogLine(2, "failed."); (thrownExceptions = thrownExceptions ?? new List <Exception>()).Add(e); Logger.LogException(null, null, null, xamlFilePath, e); Logger.LogLine(4, e.StackTrace); continue; } if (Type != null) { InitCompForType = initComp; } Logger.LogLine(2, "done."); if (OptimizeIL) { Logger.LogString(2, " Optimizing IL... "); initComp.Body.Optimize(); Logger.LogLine(2, "done"); } Logger.LogLine(2, ""); #pragma warning disable 0618 if (OutputGeneratedILAsCode) { Logger.LogLine(2, " Decompiling option has been removed. Use a 3rd party decompiler to admire the beauty of the IL generated"); } #pragma warning restore 0618 resourcesToPrune.Add(resource); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { Logger.LogLine(2, " Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { Logger.LogString(2, " Removing {0}... ", resource.Name); module.Resources.Remove(resource); Logger.LogLine(2, "done"); } } Logger.LogLine(2, ""); } if (!hasCompiledXamlResources) { Logger.LogLine(1, "No compiled resources. Skipping writing assembly."); return(success); } if (ReadOnly) { return(success); } Logger.LogString(1, "Writing the assembly... "); try { assemblyDefinition.Write(new WriterParameters { WriteSymbols = debug, }); Logger.LogLine(1, "done."); } catch (Exception e) { Logger.LogLine(1, "failed."); Logger.LogException(null, null, null, null, e); (thrownExceptions = thrownExceptions ?? new List <Exception>()).Add(e); Logger.LogLine(4, e.StackTrace); success = false; } } return(success); }
public override bool Execute(IList <Exception> thrownExceptions) { Logger = Logger ?? new Logger(null, Verbosity); Logger.LogLine(1, "Compiling Xaml"); Logger.LogLine(1, "\nAssembly: {0}", Assembly); if (!string.IsNullOrEmpty(DependencyPaths)) { Logger.LogLine(1, "DependencyPaths: \t{0}", DependencyPaths); } if (!string.IsNullOrEmpty(ReferencePath)) { Logger.LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/")); } Logger.LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols); var skipassembly = true; //change this to false to enable XamlC by default bool success = true; if (!File.Exists(Assembly)) { Logger.LogLine(1, "Assembly file not found. Skipping XamlC."); return(true); } var resolver = new XamlCAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { Logger.LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); Logger.LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); } } var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters { AssemblyResolver = resolver, ReadSymbols = DebugSymbols }); CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } Logger.LogLine(2, " Module: {0}", module.Name); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { Logger.LogString(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { Logger.LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { Logger.LogLine(2, "no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (Type != null) { skiptype = !(Type == classname); } if (skiptype) { Logger.LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { Logger.LogLine(2, "no InitializeComponent found... skipped."); continue; } Logger.LogLine(2, ""); CustomAttribute xamlFilePathAttr; var xamlFilePath = typeDef.HasCustomAttributes && (xamlFilePathAttr = typeDef.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlFilePathAttribute")) != null ? (string)xamlFilePathAttr.ConstructorArguments [0].Value : resource.Name; var initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime"); if (initCompRuntime != null) { Logger.LogLine(2, " __InitComponentRuntime already exists... not duplicating"); } else { Logger.LogString(2, " Duplicating {0}.InitializeComponent () into {0}.__InitComponentRuntime ... ", typeDef.Name); initCompRuntime = DuplicateMethodDef(typeDef, initComp, "__InitComponentRuntime"); Logger.LogLine(2, "done."); } Logger.LogString(2, " Parsing Xaml... "); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { Logger.LogLine(2, "failed."); continue; } Logger.LogLine(2, "done."); hasCompiledXamlResources = true; Logger.LogString(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); Exception e; if (!TryCoreCompile(initComp, initCompRuntime, rootnode, out e)) { success = false; Logger.LogLine(2, "failed."); thrownExceptions?.Add(e); Logger.LogException(null, null, null, xamlFilePath, e); Logger.LogLine(4, e.StackTrace); continue; } Logger.LogLine(2, "done."); if (OptimizeIL) { Logger.LogString(2, " Optimizing IL... "); initComp.Body.OptimizeMacros(); Logger.LogLine(2, "done"); } if (OutputGeneratedILAsCode) { var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs"); Logger.LogString(2, " Decompiling {0} into {1}...", typeDef.FullName, filepath); var decompilerContext = new DecompilerContext(module); using (var writer = new StreamWriter(filepath)) { var output = new PlainTextOutput(writer); var codeDomBuilder = new AstBuilder(decompilerContext); codeDomBuilder.AddType(typeDef); codeDomBuilder.GenerateCode(output); } Logger.LogLine(2, "done"); } resourcesToPrune.Add(resource); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { Logger.LogLine(2, " Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { Logger.LogString(2, " Removing {0}... ", resource.Name); module.Resources.Remove(resource); Logger.LogLine(2, "done"); } } Logger.LogLine(2, ""); } if (!hasCompiledXamlResources) { Logger.LogLine(1, "No compiled resources. Skipping writing assembly."); return(success); } Logger.LogString(1, "Writing the assembly... "); try { assemblyDefinition.Write(Assembly, new WriterParameters { WriteSymbols = DebugSymbols }); Logger.LogLine(1, "done."); } catch (Exception e) { Logger.LogLine(1, "failed."); Logger.LogException(null, null, null, null, e); thrownExceptions?.Add(e); Logger.LogLine(4, e.StackTrace); success = false; } return(success); }
public override bool Execute(out IList <Exception> thrownExceptions) { if (true == PrintReferenceAssemblies) { PrintParam(@"XamlC_Log.txt", "ReferencePath is " + ReferencePath); } LoggingHelper.LogWarning("Assembly is " + Assembly); thrownExceptions = null; LoggingHelper.LogMessage(Normal, $"{new string(' ', 0)}Compiling Xaml, assembly: {Assembly}"); var skipassembly = !CompileByDefault; bool success = true; if (!File.Exists(Assembly)) { throw new Exception(String.Format("Assembly file {0} is not exist", Assembly)); //LoggingHelper.LogMessage(Normal, $"{new string(' ', 2)}Assembly file not found. Skipping XamlC."); //return true; } s_xmlnsDefinitions.Clear(); var resolver = DefaultAssemblyResolver ?? new XamlCAssemblyResolver(); if (resolver is XamlCAssemblyResolver xamlCResolver) { if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {dep}"); xamlCResolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { GatherAssemblyInfo(p); var searchpath = System.IO.Path.GetDirectoryName(p); LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {searchpath}"); xamlCResolver.AddSearchDirectory(searchpath); } } } else { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Ignoring dependency and reference paths due to an unsupported resolver"); } var readerParameters = new ReaderParameters { AssemblyResolver = resolver, ReadWrite = !ReadOnly, ReadSymbols = NeedDebug, }; using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(System.IO.Path.GetFullPath(Assembly), readerParameters)) { if (null != XamlFilePath) { return(GenerateEXaml(XamlFilePath, assemblyDefinition.MainModule, out thrownExceptions)); } CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Tizen.NUI.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Tizen.NUI.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Module: {module.Name}"); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); string classname; if (!resource.IsXaml(module, out classname)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Tizen.NUI.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (Type != null) { skiptype = !(Type == classname); } if (skiptype && !ForceCompile) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilationAttribute set to Skip and not Compile... skipped."); continue; } bool currentRetOfType = false; IList <Exception> currentExceptionsOfType = null; if (UseInjection) { XamlOptimization = 1; } LoggingHelper.LogWarning($"XamlOptimization is {XamlOptimization}."); if (0 == XamlOptimization) {//Use Xaml currentRetOfType = true; } else if (1 == XamlOptimization) { currentRetOfType = DoInjection(typeDef, resource, out currentExceptionsOfType); } else { currentRetOfType = GenerateEXaml(typeDef, resource, out currentExceptionsOfType); if (currentRetOfType) { InjectionMethodGetEXamlPath(typeDef); } } if (null != currentExceptionsOfType) { if (null == thrownExceptions) { thrownExceptions = new List <Exception>(); } foreach (var e in currentExceptionsOfType) { thrownExceptions.Add(e); } } if (false == currentRetOfType) { success = false; continue; } resourcesToPrune.Add(resource); } if (hasCompiledXamlResources) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Changing the module MVID"); module.Mvid = Guid.NewGuid(); LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}done."); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Removing {resource.Name}"); module.Resources.Remove(resource); LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } } } if (!hasCompiledXamlResources) { LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}No compiled resources. Skipping writing assembly."); return(success); } if (ReadOnly) { return(success); } LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}Writing the assembly"); try { assemblyDefinition.Write(new WriterParameters { WriteSymbols = NeedDebug, }); LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}done."); } catch (Exception e) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}failed."); LoggingHelper.LogErrorFromException(e); (thrownExceptions = thrownExceptions ?? new List <Exception>()).Add(e); LoggingHelper.LogMessage(Low, e.StackTrace); success = false; } } return(success); }
public override bool Execute(out IList <Exception> thrownExceptions) { thrownExceptions = null; LoggingHelper.LogMessage(Normal, $"{new string(' ', 0)}Compiling Xaml, assembly: {Assembly}"); var skipassembly = !CompileByDefault; bool success = true; if (!File.Exists(Assembly)) { LoggingHelper.LogMessage(Normal, $"{new string(' ', 2)}Assembly file not found. Skipping XamlC."); return(true); } using (var fallbackResolver = DefaultAssemblyResolver == null ? new XamlCAssemblyResolver() : null) { var resolver = DefaultAssemblyResolver ?? fallbackResolver; if (resolver is XamlCAssemblyResolver xamlCResolver) { if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';').Distinct()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {dep}"); xamlCResolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';').Distinct(); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Adding searchpath {searchpath}"); xamlCResolver.AddSearchDirectory(searchpath); } } } else { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Ignoring dependency and reference paths due to an unsupported resolver"); } var debug = DebugSymbols || (!string.IsNullOrEmpty(DebugType) && DebugType.ToLowerInvariant() != "none"); var readerParameters = new ReaderParameters { AssemblyResolver = resolver, ReadWrite = !ValidateOnly, ReadSymbols = debug && !ValidateOnly, // We don't need symbols for ValidateOnly, since we won't be writing }; using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), readerParameters)) { CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Module: {module.Name}"); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); string classname; if (!resource.IsXaml(module, out classname)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (Type != null) { skiptype = !(Type == classname); } if (skiptype && !ForceCompile) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilationAttribute set to Skip and not Compile... skipped."); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}no InitializeComponent found... skipped."); continue; } CustomAttribute xamlFilePathAttr; var xamlFilePath = typeDef.HasCustomAttributes && (xamlFilePathAttr = typeDef.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlFilePathAttribute")) != null ? (string)xamlFilePathAttr.ConstructorArguments[0].Value : resource.Name; MethodDefinition initCompRuntime = null; if (!ValidateOnly) { initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime"); if (initCompRuntime != null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}__InitComponentRuntime already exists... not creating"); } else { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Creating empty {typeDef.Name}.__InitComponentRuntime"); initCompRuntime = new MethodDefinition("__InitComponentRuntime", initComp.Attributes, initComp.ReturnType); initCompRuntime.Body.InitLocals = true; LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Copying body of InitializeComponent to __InitComponentRuntime"); initCompRuntime.Body = new MethodBody(initCompRuntime); var iCRIl = initCompRuntime.Body.GetILProcessor(); foreach (var instr in initComp.Body.Instructions) { iCRIl.Append(instr); } initComp.Body.Instructions.Clear(); initComp.Body.GetILProcessor().Emit(OpCodes.Ret); initComp.Body.InitLocals = true; typeDef.Methods.Add(initCompRuntime); LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } } LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Parsing Xaml"); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed."); continue; } LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); hasCompiledXamlResources = true; LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing {0}.InitializeComponent ()"); Exception e; if (!TryCoreCompile(initComp, initCompRuntime, rootnode, xamlFilePath, out e)) { success = false; LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed."); (thrownExceptions = thrownExceptions ?? new List <Exception>()).Add(e); if (e is XamlParseException xpe) { LoggingHelper.LogError(null, null, null, xamlFilePath, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message, xpe.HelpLink, xpe.Source); } else if (e is XmlException xe) { LoggingHelper.LogError(null, null, null, xamlFilePath, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source); } else { LoggingHelper.LogError(null, null, null, xamlFilePath, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); } LoggingHelper.LogMessage(Low, e.StackTrace); continue; } if (Type != null) { InitCompForType = initComp; } LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); if (ValidateOnly) { continue; } if (OptimizeIL) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Optimizing IL"); initComp.Body.Optimize(); LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } #pragma warning disable 0618 if (OutputGeneratedILAsCode) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Decompiling option has been removed. Use a 3rd party decompiler to admire the beauty of the IL generated"); } #pragma warning restore 0618 resourcesToPrune.Add(resource); } if (hasCompiledXamlResources) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Changing the module MVID"); module.Mvid = Guid.NewGuid(); LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}done."); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Removing {resource.Name}"); module.Resources.Remove(resource); LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}done."); } } } if (ValidateOnly) { LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}ValidateOnly=True. Skipping writing assembly."); return(success); } if (!hasCompiledXamlResources) { LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}No compiled resources. Skipping writing assembly."); return(success); } LoggingHelper.LogMessage(Low, $"{new string(' ', 0)}Writing the assembly"); try { assemblyDefinition.Write(new WriterParameters { WriteSymbols = debug, }); LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}done."); } catch (Exception e) { LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}failed."); LoggingHelper.LogErrorFromException(e); (thrownExceptions = thrownExceptions ?? new List <Exception>()).Add(e); LoggingHelper.LogMessage(Low, e.StackTrace); success = false; } } } return(success); }
public bool Compile() { LogLine(1, "Compiling Xaml"); LogLine(1, "\nAssembly: {0}", Assembly); if (!string.IsNullOrEmpty(DependencyPaths)) { LogLine(1, "DependencyPaths: \t{0}", DependencyPaths); } if (!string.IsNullOrEmpty(ReferencePath)) { LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/")); } LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols); var skipassembly = true; //change this to false to enable XamlC by default bool success = true; if (!File.Exists(Assembly)) { LogLine(1, "Assembly file not found. Skipping XamlC."); return(true); } var resolver = new XamlCAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); // LogLine (3, "Referencing {0}", p); // resolver.AddAssembly (p); } } var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters { AssemblyResolver = resolver, ReadSymbols = DebugSymbols }); CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } LogLine(2, " Module: {0}", module.Name); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LogString(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LogLine(2, "no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (skiptype) { LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LogLine(2, "no InitializeComponent found... skipped."); continue; } LogLine(2, ""); var initCompRuntime = typeDef.Methods.FirstOrDefault(md => md.Name == "__InitComponentRuntime"); if (initCompRuntime != null) { LogLine(2, " __InitComponentRuntime already exists... not duplicating"); } else { LogString(2, " Duplicating {0}.InitializeComponent () into {0}.__InitComponentRuntime ... ", typeDef.Name); initCompRuntime = DuplicateMethodDef(typeDef, initComp, "__InitComponentRuntime"); LogLine(2, "done."); } LogString(2, " Parsing Xaml... "); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { LogLine(2, "failed."); continue; } LogLine(2, "done."); hasCompiledXamlResources = true; try { LogString(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); var body = new MethodBody(initComp); var il = body.GetILProcessor(); il.Emit(OpCodes.Nop); // Generating branching code for the Previewer // IL_0007: call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider() // IL_000c: brfalse IL_0031 // IL_0011: call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider() // IL_0016: ldarg.0 // IL_0017: call instance class [mscorlib]System.Type object::GetType() // IL_001c: callvirt instance !1 class [mscorlib]System.Func`2<class [mscorlib]System.Type, string>::Invoke(!0) // IL_0021: brfalse IL_0031 // IL_0026: ldarg.0 // IL_0027: call instance void class Xamarin.Forms.Xaml.UnitTests.XamlLoaderGetXamlForTypeTests::__InitComponentRuntime() // IL_002c: ret // IL_0031: nop var nop = Instruction.Create(OpCodes.Nop); var getXamlFileProvider = body.Method.Module.Import(body.Method.Module.Import(typeof(Xamarin.Forms.Xaml.Internals.XamlLoader)) .Resolve() .Properties.FirstOrDefault(pd => pd.Name == "XamlFileProvider") .GetMethod); il.Emit(OpCodes.Call, getXamlFileProvider); il.Emit(OpCodes.Brfalse, nop); il.Emit(OpCodes.Call, getXamlFileProvider); il.Emit(OpCodes.Ldarg_0); var getType = body.Method.Module.Import(body.Method.Module.Import(typeof(object)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "GetType")); il.Emit(OpCodes.Call, getType); var func = body.Method.Module.Import(body.Method.Module.Import(typeof(Func <Type, string>)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "Invoke")); func = func.ResolveGenericParameters(body.Method.Module.Import(typeof(Func <Type, string>)), body.Method.Module); il.Emit(OpCodes.Callvirt, func); il.Emit(OpCodes.Brfalse, nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, initCompRuntime); il.Emit(OpCodes.Ret); il.Append(nop); var visitorContext = new ILContext(il, body); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); rootnode.Accept(new PruneIgnoredNodesVisitor(), null); rootnode.Accept(new CreateObjectVisitor(visitorContext), null); rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); rootnode.Accept(new SetFieldVisitor(visitorContext), null); rootnode.Accept(new SetResourcesVisitor(visitorContext), null); rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); il.Emit(OpCodes.Ret); initComp.Body = body; } catch (XamlParseException xpe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message, xpe.HelpLink, xpe.Source); LogLine(4, xpe.StackTrace); success = false; continue; } catch (XmlException xe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source); LogLine(4, xe.StackTrace); success = false; continue; } catch (Exception e) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; continue; } LogLine(2, "done."); if (OptimizeIL) { LogString(2, " Optimizing IL... "); initComp.Body.OptimizeMacros(); LogLine(2, "done"); } if (OutputGeneratedILAsCode) { var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs"); LogString(2, " Decompiling {0} into {1}...", typeDef.FullName, filepath); var decompilerContext = new DecompilerContext(module); using (var writer = new StreamWriter(filepath)) { var output = new PlainTextOutput(writer); var codeDomBuilder = new AstBuilder(decompilerContext); codeDomBuilder.AddType(typeDef); codeDomBuilder.GenerateCode(output); } LogLine(2, "done"); } resourcesToPrune.Add(resource); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { LogLine(2, " Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { LogString(2, " Removing {0}... ", resource.Name); module.Resources.Remove(resource); LogLine(2, "done"); } } LogLine(2, ""); } if (!hasCompiledXamlResources) { LogLine(1, "No compiled resources. Skipping writing assembly."); return(success); } LogString(1, "Writing the assembly... "); try { assemblyDefinition.Write(Assembly, new WriterParameters { WriteSymbols = DebugSymbols }); LogLine(1, "done."); } catch (Exception e) { LogLine(1, "failed."); LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; } return(success); }
public override bool Execute() { InMsBuild = true; Verbosity = Int32.MaxValue; LogLine(1, "Preparing debug code for xamlc"); LogLine(1, "\nAssembly: {0}", Assembly); var resolver = new DefaultAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); // LogLine (3, "Referencing {0}", p); // resolver.AddAssembly (p); } } var assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly, new ReaderParameters { //ReadSymbols = DebugSymbols, AssemblyResolver = resolver }); foreach (var module in assemblyDefinition.Modules) { LogLine(2, " Module: {0}", module.Name); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LogString(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LogLine(2, "no type found... skipped."); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LogLine(2, "no InitializeComponent found... skipped."); continue; } if (typeDef.Methods.FirstOrDefault(md => md.Name == "InitCompRuntime") != null) { LogLine(2, "InitCompRuntime already exists... skipped"); continue; } LogLine(2, ""); LogString(2, " Duplicating {0}.InitializeComponent () into {0}.InitCompRuntime ... ", typeDef.Name); var initCompRuntime = new MethodDefinition("InitCompRuntime", initComp.Attributes, initComp.ReturnType); initCompRuntime.Body = initComp.Body; typeDef.Methods.Add(initCompRuntime); LogLine(2, "done."); // IL_0000: ldarg.0 // IL_0001: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.ContentPage::'.ctor'() // // IL_0006: nop // IL_0007: ldarg.1 // IL_0008: brfalse IL_0018 // // IL_000d: ldarg.0 // IL_000e: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitializeComponent() // IL_0013: br IL_001e // // IL_0018: ldarg.0 // IL_0019: callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitCompRuntime() // IL_001e: ret var altCtor = typeDef.Methods.Where( md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType == module.TypeSystem.Boolean) .FirstOrDefault(); if (altCtor != null) { LogString(2, " Replacing body of {0}.{0} (bool {1}) ... ", typeDef.Name, altCtor.Parameters[0].Name); } else { LogString(2, " Adding {0}.{0} (bool useCompiledXaml) ... ", typeDef.Name); altCtor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, module.TypeSystem.Void); altCtor.Parameters.Add(new ParameterDefinition("useCompiledXaml", ParameterAttributes.None, module.TypeSystem.Boolean)); } var body = new MethodBody(altCtor); var il = body.GetILProcessor(); var br2 = Instruction.Create(OpCodes.Ldarg_0); var ret = Instruction.Create(OpCodes.Ret); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, module.Import(typeDef.BaseType.Resolve().GetConstructors().First(c => c.HasParameters == false))); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Brfalse, br2); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, initComp); il.Emit(OpCodes.Br, ret); il.Append(br2); il.Emit(OpCodes.Callvirt, initCompRuntime); il.Append(ret); altCtor.Body = body; if (!typeDef.Methods.Contains(altCtor)) { typeDef.Methods.Add(altCtor); } LogLine(2, "done."); } LogLine(2, ""); } LogString(1, "Writing the assembly... "); assemblyDefinition.Write(Assembly, new WriterParameters { WriteSymbols = DebugSymbols }); LogLine(1, "done."); return(true); }
public bool Compile() { LogLine(1, "Compiling Xaml"); LogLine(1, "\nAssembly: {0}", Assembly); if (!string.IsNullOrEmpty(DependencyPaths)) { LogLine(1, "DependencyPaths: \t{0}", DependencyPaths); } if (!string.IsNullOrEmpty(ReferencePath)) { LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/")); } LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols); var skipassembly = true; //change this to false to enable XamlC by default bool success = true; if (!File.Exists(Assembly)) { LogLine(1, "Assembly file not found. Skipping XamlC."); return(true); } var resolver = new XamlCAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); // LogLine (3, "Referencing {0}", p); // resolver.AddAssembly (p); } } var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters { AssemblyResolver = resolver, ReadSymbols = DebugSymbols }); CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } LogLine(2, " Module: {0}", module.Name); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { Log(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LogLine(2, "no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (skiptype) { LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LogLine(2, "no InitializeComponent found... skipped."); continue; } LogLine(2, ""); Log(2, " Parsing Xaml... "); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { LogLine(2, "failed."); continue; } LogLine(2, "done."); hasCompiledXamlResources = true; try { Log(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); var body = new MethodBody(initComp); var il = body.GetILProcessor(); il.Emit(OpCodes.Nop); var visitorContext = new ILContext(il, body); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); rootnode.Accept(new CreateObjectVisitor(visitorContext), null); rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); rootnode.Accept(new SetFieldVisitor(visitorContext), null); rootnode.Accept(new SetResourcesVisitor(visitorContext), null); rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); il.Emit(OpCodes.Ret); initComp.Body = body; } catch (XamlParseException xpe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message, xpe.HelpLink, xpe.Source); LogLine(4, xpe.StackTrace); success = false; continue; } catch (XmlException xe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source); LogLine(4, xe.StackTrace); success = false; continue; } catch (Exception e) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; continue; } LogLine(2, "done."); if (OptimizeIL) { Log(2, " Optimizing IL... "); initComp.Body.OptimizeMacros(); LogLine(2, "done"); } if (OutputGeneratedILAsCode) { var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs"); Log(2, " Decompiling {0} into {1}...", typeDef.FullName, filepath); var decompilerContext = new DecompilerContext(module); using (var writer = new StreamWriter(filepath)) { var output = new PlainTextOutput(writer); var codeDomBuilder = new AstBuilder(decompilerContext); codeDomBuilder.AddType(typeDef); codeDomBuilder.GenerateCode(output); } LogLine(2, "done"); } resourcesToPrune.Add(resource); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { LogLine(2, " Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { Log(2, " Removing {0}... ", resource.Name); module.Resources.Remove(resource); LogLine(2, "done"); } } LogLine(2, ""); } if (!hasCompiledXamlResources) { LogLine(1, "No compiled resources. Skipping writing assembly."); return(success); } Log(1, "Writing the assembly... "); try { assemblyDefinition.Write(Assembly, new WriterParameters { WriteSymbols = DebugSymbols }); LogLine(1, "done."); } catch (Exception e) { LogLine(1, "failed."); LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; } return(success); }