diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2016-09-08 21:01:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-08 21:01:09 +0200 |
commit | 36822e614d6be3fa033410d87408c404288db4c3 (patch) | |
tree | e2529d9f71dde4864f44d73b7a8ff4689309f25a /Xamarin.Forms.Build.Tasks | |
parent | 1f84a4955c93544192f44ba6af5d3593554dc116 (diff) | |
download | xamarin-forms-36822e614d6be3fa033410d87408c404288db4c3.tar.gz xamarin-forms-36822e614d6be3fa033410d87408c404288db4c3.tar.bz2 xamarin-forms-36822e614d6be3fa033410d87408c404288db4c3.zip |
[XamlC] throw exception on missing property (#336)
* Added unit test for 43450
* fix test
* [XamlC] instrument the compiler so we can test it
* [XamlC] throw on missing property
Diffstat (limited to 'Xamarin.Forms.Build.Tasks')
-rw-r--r-- | Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs | 4 | ||||
-rw-r--r-- | Xamarin.Forms.Build.Tasks/XamlCTask.cs | 177 |
2 files changed, 97 insertions, 84 deletions
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs index 462a8962..9bc09ce9 100644 --- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs +++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs @@ -169,7 +169,9 @@ namespace Xamarin.Forms.Build.Tasks Context.IL.Emit(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") Context.IL.Emit(OpCodes.Pop); - } + } else + throw new XamlParseException(string.Format("Property {0} not found", localname), node); + } } diff --git a/Xamarin.Forms.Build.Tasks/XamlCTask.cs b/Xamarin.Forms.Build.Tasks/XamlCTask.cs index b119b4e9..206fc452 100644 --- a/Xamarin.Forms.Build.Tasks/XamlCTask.cs +++ b/Xamarin.Forms.Build.Tasks/XamlCTask.cs @@ -40,12 +40,26 @@ namespace Xamarin.Forms.Build.Tasks protected bool InMsBuild { get; set; } + internal string Type { get; set; } + public override bool Execute() { InMsBuild = true; return Compile(); } + protected void LogException(string subcategory, string errorCode, string helpKeyword, string file, Exception e) + { + var xpe = e as XamlParseException; + var xe = e as XmlException; + if (xpe != null) + LogError(subcategory, errorCode, helpKeyword, file, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message, xpe.HelpLink, xpe.Source); + else if (xe != null) + LogError(subcategory, errorCode, helpKeyword, file, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source); + else + LogError(subcategory, errorCode, helpKeyword, file, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); + } + protected void LogError(string subcategory, string errorCode, string helpKeyword, string file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber, string message, params object[] messageArgs) { @@ -109,12 +123,12 @@ namespace Xamarin.Forms.Build.Tasks InMsBuild = false, DependencyPaths = dependencyPaths, ReferencePath = referencePath, - OutputGeneratedILAsCode = outputCSharp + OutputGeneratedILAsCode = outputCSharp, }; xamlc.Compile(); } - public bool Compile() + public bool Compile(IList<Exception> thrownExceptions = null) { LogLine(1, "Compiling Xaml"); LogLine(1, "\nAssembly: {0}", Assembly); @@ -150,8 +164,6 @@ namespace Xamarin.Forms.Build.Tasks var searchpath = Path.GetDirectoryName(p); LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); - // LogLine (3, "Referencing {0}", p); - // resolver.AddAssembly (p); } } @@ -218,6 +230,10 @@ namespace Xamarin.Forms.Build.Tasks if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) skiptype = false; } + + if (Type != null) + skiptype = !(Type == classname); + if (skiptype) { LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); @@ -252,87 +268,14 @@ namespace Xamarin.Forms.Build.Tasks 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); + LogString(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); + Exception e; + if (!TryCoreCompile(initComp, initCompRuntime, rootnode, out e)) { 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); + thrownExceptions?.Add(e); + LogException(null, null, null, resource.Name, e); LogLine(4, e.StackTrace); - success = false; continue; } LogLine(2, "done."); @@ -395,7 +338,8 @@ namespace Xamarin.Forms.Build.Tasks catch (Exception e) { LogLine(1, "failed."); - LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); + LogException(null, null, null, null, e); + thrownExceptions?.Add(e); LogLine(4, e.StackTrace); success = false; } @@ -403,6 +347,73 @@ namespace Xamarin.Forms.Build.Tasks return success; } + bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, out Exception exception) + { + try { + var body = new MethodBody(initComp); + var il = body.GetILProcessor(); + il.Emit(OpCodes.Nop); + + if (initCompRuntime != null) { + // 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; + exception = null; + return true; + } catch (Exception e) { + exception = e; + return false; + } + } + protected static MethodDefinition DuplicateMethodDef(TypeDefinition typeDef, MethodDefinition methodDef, string newName) { var dup = new MethodDefinition(newName, methodDef.Attributes, methodDef.ReturnType); |