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) { 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 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; }
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 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); }