summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs4
-rw-r--r--Xamarin.Forms.Build.Tasks/XamlCTask.cs177
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml15
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml.cs32
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/MockCompiler.cs30
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj11
6 files changed, 184 insertions, 85 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);
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml
new file mode 100644
index 00000000..cc234879
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Bz43450">
+ <Grid>
+ <Grid.RowDefinition>
+ <RowDefinition Height="20"/>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="20"/>
+ </Grid.RowDefinition>
+ <BoxView BackgroundColor="Red"/>
+ <BoxView Grid.Row="1" BackgroundColor="Yellow"/>
+ <BoxView Grid.Row="2" BackgroundColor="Green"/>
+ </Grid>
+</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml.cs
new file mode 100644
index 00000000..b3346b37
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Bz43450.xaml.cs
@@ -0,0 +1,32 @@
+using NUnit.Framework;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ [XamlCompilation(XamlCompilationOptions.Skip)]
+ public partial class Bz43450 : ContentPage
+ {
+ public Bz43450()
+ {
+ InitializeComponent();
+ }
+
+ public Bz43450(bool useCompiledXaml)
+ {
+ //this stub will be replaced at compile time
+ }
+
+ [TestFixture]
+ class Tests
+ {
+ [TestCase(true)]
+ [TestCase(false)]
+ public void DoesNotAllowGridRowDefinition(bool useCompiledXaml)
+ {
+ if (!useCompiledXaml)
+ Assert.Throws<XamlParseException>(() => new Bz43450(useCompiledXaml));
+ else
+ Assert.Throws<XamlParseException>(() => MockCompiler.Compile(typeof(Bz43450)));
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/MockCompiler.cs b/Xamarin.Forms.Xaml.UnitTests/MockCompiler.cs
new file mode 100644
index 00000000..404169b3
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/MockCompiler.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Xamarin.Forms.Build.Tasks;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public static class MockCompiler
+ {
+ public static void Compile(Type type)
+ {
+ var assembly = type.Assembly.Location;
+ var refs = from an in type.Assembly.GetReferencedAssemblies()
+ let a = System.Reflection.Assembly.Load(an)
+ select a.Location;
+
+ var xamlc = new XamlCTask {
+ Assembly = assembly,
+ ReferencePath = string.Join(";", refs),
+ KeepXamlResources = true,
+ Type = type.FullName
+ };
+
+ var exceptions = new List<Exception>();
+ if (!xamlc.Compile(exceptions) && exceptions.Any())
+ throw exceptions [0];
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
index 26bf6d41..16f54e88 100644
--- a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
+++ b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
@@ -81,6 +81,9 @@
<Link>MockPlatformServices.cs</Link>
</Compile>
<Compile Include="FontConverterTests.cs" />
+ <Compile Include="Issues\Bz43450.xaml.cs">
+ <DependentUpon>Bz43450.xaml</DependentUpon>
+ </Compile>
<Compile Include="Issues\Bz41296.xaml.cs">
<DependentUpon>Bz41296.xaml</DependentUpon>
</Compile>
@@ -362,6 +365,7 @@
<Compile Include="NativeViewsAndBindings.xaml.cs">
<DependentUpon>NativeViewsAndBindings.xaml</DependentUpon>
</Compile>
+ <Compile Include="MockCompiler.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
@@ -669,4 +673,9 @@
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
-</Project> \ No newline at end of file
+ <ItemGroup>
+ <EmbeddedResource Include="Issues\Bz43450.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
+ </ItemGroup>
+</Project>