diff options
author | Stephane Delcroix <stephane@delcroix.org> | 2017-04-28 10:39:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-28 10:39:16 +0200 |
commit | 84ba9edce46967d34b5c0cc92a0ca117d712ff7e (patch) | |
tree | 985915c6f8365f6791def072a68c23549bb83507 | |
parent | 6ee219ca1db3f4d43370d39865c705d9c99ad38e (diff) | |
download | xamarin-forms-84ba9edce46967d34b5c0cc92a0ca117d712ff7e.tar.gz xamarin-forms-84ba9edce46967d34b5c0cc92a0ca117d712ff7e.tar.bz2 xamarin-forms-84ba9edce46967d34b5c0cc92a0ca117d712ff7e.zip |
[XamlG] supports x:FieldModifier (#878)
* [XamlG] supports x:FieldModifier
* adapt test as duplicate fields are now caught at XamlG time
* [XamlG] supports UWP values in addition of WPF's for x:FieldModifier
-rw-r--r-- | Xamarin.Forms.Build.Tasks/XamlGTask.cs | 105 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml | 11 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml.cs | 42 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml | 18 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs | 10 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj | 6 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs | 110 | ||||
-rw-r--r-- | Xamarin.Forms.Xaml/XamlParser.cs | 4 |
8 files changed, 210 insertions, 96 deletions
diff --git a/Xamarin.Forms.Build.Tasks/XamlGTask.cs b/Xamarin.Forms.Build.Tasks/XamlGTask.cs index b13eec69..35db159f 100644 --- a/Xamarin.Forms.Build.Tasks/XamlGTask.cs +++ b/Xamarin.Forms.Build.Tasks/XamlGTask.cs @@ -60,7 +60,7 @@ namespace Xamarin.Forms.Build.Tasks } internal static void ParseXaml(TextReader xaml, out string rootType, out string rootNs, out CodeTypeReference baseType, - out IDictionary<string, CodeTypeReference> namesAndTypes) + out IEnumerable<CodeMemberField> namedFields) { var xmlDoc = new XmlDocument(); xmlDoc.Load(xaml); @@ -76,7 +76,7 @@ namespace Xamarin.Forms.Build.Tasks rootType = null; rootNs = null; baseType = null; - namesAndTypes = null; + namedFields = null; return; } @@ -96,18 +96,16 @@ namespace Xamarin.Forms.Build.Tasks rootType = null; rootNs = null; baseType = null; - namesAndTypes = null; + namedFields = null; return; } string rootAsm, targetPlatform; XmlnsHelper.ParseXmlns(rootClass.Value, out rootType, out rootNs, out rootAsm, out targetPlatform); - namesAndTypes = GetNamesAndTypes(root, nsmgr); + namedFields = GetCodeMemberFields(root, nsmgr); - var typeArgsAttr = root.Attributes["TypeArguments", XAML2006] - ?? root.Attributes["TypeArguments", XAML2009]; - - var xmlType = new XmlType(root.NamespaceURI, root.LocalName, typeArgsAttr != null ? TypeArgumentsParser.ParseExpression(typeArgsAttr.Value, nsmgr, null): null); + var typeArguments = GetAttributeValue(root, "TypeArguments", XAML2006, XAML2009); + var xmlType = new XmlType(root.NamespaceURI, root.LocalName, typeArguments != null ? TypeArgumentsParser.ParseExpression(typeArguments, nsmgr, null): null); baseType = GetType(xmlType, root.GetNamespaceOfPrefix); } @@ -117,7 +115,7 @@ namespace Xamarin.Forms.Build.Tasks new CodeAttributeArgument(new CodePrimitiveExpression("0.0.0.0"))); internal static void GenerateCode(string rootType, string rootNs, CodeTypeReference baseType, - IDictionary<string, CodeTypeReference> namesAndTypes, string xamlFile, string outFile) + IEnumerable<CodeMemberField> namedFields, string xamlFile, string outFile) { if (rootType == null) { @@ -151,28 +149,18 @@ namespace Xamarin.Forms.Build.Tasks new CodeTypeReferenceExpression(new CodeTypeReference($"global::{typeof(Extensions).FullName}")), "LoadFromXaml", new CodeThisReferenceExpression(), new CodeTypeOfExpression(declType.Name))); - foreach (var entry in namesAndTypes) + foreach (var namedField in namedFields) { - string name = entry.Key; - var type = entry.Value; - - var field = new CodeMemberField - { - Name = name, - Type = type, - CustomAttributes = { GeneratedCodeAttrDecl } - }; - - declType.Members.Add(field); + declType.Members.Add(namedField); var find_invoke = new CodeMethodInvokeExpression( new CodeMethodReferenceExpression( new CodeTypeReferenceExpression(new CodeTypeReference($"global::{typeof(NameScopeExtensions).FullName}")), - "FindByName", type), - new CodeThisReferenceExpression(), new CodePrimitiveExpression(name)); + "FindByName", namedField.Type), + new CodeThisReferenceExpression(), new CodePrimitiveExpression(namedField.Name)); CodeAssignStatement assign = new CodeAssignStatement( - new CodeVariableReferenceExpression(name), find_invoke); + new CodeVariableReferenceExpression(namedField.Name), find_invoke); initcomp.Statements.Add(assign); } @@ -185,21 +173,19 @@ namespace Xamarin.Forms.Build.Tasks { string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string, CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> namedFields; using (StreamReader reader = File.OpenText(xamlFile)) - ParseXaml(reader, out rootType, out rootNs, out baseType, out namesAndTypes); + ParseXaml(reader, out rootType, out rootNs, out baseType, out namedFields); - GenerateCode(rootType, rootNs, baseType, namesAndTypes, Path.GetFullPath(xamlFile), outFile); + GenerateCode(rootType, rootNs, baseType, namedFields, Path.GetFullPath(xamlFile), outFile); } - static Dictionary<string, CodeTypeReference> GetNamesAndTypes(XmlNode root, XmlNamespaceManager nsmgr) + static IEnumerable<CodeMemberField> GetCodeMemberFields(XmlNode root, XmlNamespaceManager nsmgr) { - var res = new Dictionary<string, CodeTypeReference>(); - var xPrefix = nsmgr.LookupPrefix(XAML2006) ?? nsmgr.LookupPrefix(XAML2009); if (xPrefix == null) - return null; + yield break; XmlNodeList names = root.SelectNodes( @@ -210,20 +196,42 @@ namespace Xamarin.Forms.Build.Tasks // Don't take the root canvas if (node == root) continue; + var name = GetAttributeValue(node, "Name", XAML2006, XAML2009); + var typeArguments = GetAttributeValue(node, "TypeArguments", XAML2006, XAML2009); + var fieldModifier = GetAttributeValue(node, "FieldModifier", XAML2006, XAML2009); - XmlAttribute attr = node.Attributes["Name", XAML2006] - ?? node.Attributes["Name", XAML2009]; - XmlAttribute typeArgsAttr = node.Attributes["TypeArguments", XAML2006] - ?? node.Attributes["TypeArguments", XAML2009]; var xmlType = new XmlType(node.NamespaceURI, node.LocalName, - typeArgsAttr != null - ? TypeArgumentsParser.ParseExpression(typeArgsAttr.Value, nsmgr, null) + typeArguments != null + ? TypeArgumentsParser.ParseExpression(typeArguments, nsmgr, null) : null); - res[attr.Value] = GetType(xmlType, node.GetNamespaceOfPrefix); - } + var access = MemberAttributes.Private; + if (fieldModifier!=null) { + switch (fieldModifier.ToLowerInvariant()){ + default: + case "private": + access = MemberAttributes.Private; + break; + case "public": + access = MemberAttributes.Public; + break; + case "protected": + access = MemberAttributes.Family; + break; + case "internal": + case "notpublic": //WPF syntax + access = MemberAttributes.Assembly; + break; + } + } - return res; + yield return new CodeMemberField { + Name = name, + Type = GetType(xmlType, node.GetNamespaceOfPrefix), + Attributes = access, + CustomAttributes = { GeneratedCodeAttrDecl } + }; + } } static CodeTypeReference GetType(XmlType xmlType, @@ -258,5 +266,22 @@ namespace Xamarin.Forms.Build.Tasks throw new Exception($"Can't load types from xmlns {namespaceuri}"); return XmlnsHelper.ParseNamespaceFromXmlns(namespaceuri); } + + static string GetAttributeValue(XmlNode node, string localName, params string[] namespaceURIs) + { + if (node == null) + throw new ArgumentNullException(nameof(node)); + if (localName == null) + throw new ArgumentNullException(nameof(localName)); + if (namespaceURIs == null) + throw new ArgumentNullException(nameof(namespaceURIs)); + foreach (var namespaceURI in namespaceURIs) { + var attr = node.Attributes[localName, namespaceURI]; + if (attr == null) + continue; + return attr.Value; + } + return null; + } } }
\ No newline at end of file diff --git a/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml b/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml new file mode 100644 index 00000000..a4623297 --- /dev/null +++ b/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests" + x:Class="Xamarin.Forms.Xaml.UnitTests.FieldModifier"> + <StackLayout> + <Label x:Name="privateLabel" /> + <Label x:Name="internalLabel" x:FieldModifier="NotPublic" /> + <Label x:Name="publicLabel" x:FieldModifier="Public" /> + </StackLayout> +</ContentPage>
\ No newline at end of file diff --git a/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml.cs new file mode 100644 index 00000000..fde0e777 --- /dev/null +++ b/Xamarin.Forms.Xaml.UnitTests/FieldModifier.xaml.cs @@ -0,0 +1,42 @@ +using System.Linq; +using System.Reflection; +using NUnit.Framework; + +namespace Xamarin.Forms.Xaml.UnitTests +{ + public partial class FieldModifier : ContentPage + { + public FieldModifier() + { + InitializeComponent(); + } + + public FieldModifier (bool useCompiledXaml) + { + //this stub will be replaced at compile time + } + + [TestFixture] + public class FindByNameTests + { + [TestCase (false)] + [TestCase (true)] + public void TestFieldModifier (bool useCompiledXaml) + { + var layout = new FieldModifier(); + Assert.That(layout.privateLabel, Is.Not.Null); + Assert.That(layout.internalLabel, Is.Not.Null); + Assert.That(layout.publicLabel, Is.Not.Null); + + var fields = typeof(FieldModifier).GetTypeInfo().DeclaredFields; + + Assert.That(fields.First(fi => fi.Name == "privateLabel").IsPrivate, Is.True); + + Assert.That(fields.First(fi => fi.Name == "internalLabel").IsPrivate, Is.False); + Assert.That(fields.First(fi => fi.Name == "internalLabel").IsPublic, Is.False); + + Assert.That(fields.First(fi => fi.Name == "publicLabel").IsPublic, Is.True); + } + } + } +} diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml index 385619e5..8fc57819 100644 --- a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml +++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml @@ -1,10 +1,16 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?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.Issue2450"> - <StackLayout> - <Label x:Name="label0"/> - <Label x:Name="label0"/> - </StackLayout> -</ContentPage> + <ContentPage.Resources> + <ResourceDictionary> + <DataTemplate x:Key="foo"> + <ViewCell> + <Label x:Name="label0"/> + <Label x:Name="label0"/> + </ViewCell> + </DataTemplate> + </ResourceDictionary> + </ContentPage.Resources> +</ContentPage>
\ No newline at end of file diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs index 2d330934..d1a15659 100644 --- a/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs +++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Issue2450.xaml.cs @@ -29,15 +29,11 @@ namespace Xamarin.Forms.Xaml.UnitTests } [TestCase (false)] - [TestCase (true)] public void ThrowMeaningfulExceptionOnDuplicateXName (bool useCompiledXaml) { - if (useCompiledXaml) - Assert.Throws(new XamlParseExceptionConstraint(8, 10, m => m == "An element with the name \"label0\" already exists in this NameScope"), - () => MockCompiler.Compile(typeof(Issue2450))); - else - Assert.Throws(new XamlParseExceptionConstraint(8, 10, m => m == "An element with the name \"label0\" already exists in this NameScope"), - () => new Issue2450(useCompiledXaml)); + var layout = new Issue2450(useCompiledXaml); + Assert.Throws(new XamlParseExceptionConstraint(11, 13, m => m == "An element with the name \"label0\" already exists in this NameScope"), + () => (layout.Resources ["foo"] as Forms.DataTemplate).CreateContent()); } } } diff --git a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj index 123a0d59..0d98f25a 100644 --- a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj +++ b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj @@ -482,6 +482,9 @@ <Compile Include="Issues\Bz55347.xaml.cs"> <DependentUpon>Bz55347.xaml</DependentUpon> </Compile> + <Compile Include="FieldModifier.xaml.cs"> + <DependentUpon>FieldModifier.xaml</DependentUpon> + </Compile> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" /> @@ -884,6 +887,9 @@ <EmbeddedResource Include="Issues\Bz55347.xaml"> <Generator>MSBuild:UpdateDesignTimeXaml</Generator> </EmbeddedResource> + <EmbeddedResource Include="FieldModifier.xaml"> + <Generator>MSBuild:UpdateDesignTimeXaml</Generator> + </EmbeddedResource> </ItemGroup> <ItemGroup> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs index 9303539e..edf2d075 100644 --- a/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs +++ b/Xamarin.Forms.Xaml.UnitTests/XamlgTests.cs @@ -26,20 +26,20 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.NotNull (rootType); Assert.NotNull (rootNs); Assert.NotNull (baseType); - Assert.NotNull (namesAndTypes); + Assert.NotNull (codeMemberFields); Assert.AreEqual ("CustomView", rootType); Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests", rootNs); Assert.AreEqual ("Xamarin.Forms.View", baseType.BaseType); - Assert.AreEqual (1, namesAndTypes.Count); - Assert.AreEqual ("label0", namesAndTypes.First().Key); - Assert.AreEqual ("Xamarin.Forms.Label", namesAndTypes.First().Value.BaseType); + Assert.AreEqual (1, codeMemberFields.Count()); + Assert.AreEqual ("label0", codeMemberFields.First().Name); + Assert.AreEqual ("Xamarin.Forms.Label", codeMemberFields.First().Type.BaseType); } [Test] @@ -55,20 +55,20 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.NotNull (rootType); Assert.NotNull (rootNs); Assert.NotNull (baseType); - Assert.NotNull (namesAndTypes); + Assert.NotNull (codeMemberFields); Assert.AreEqual ("CustomView", rootType); Assert.AreEqual ("Xamarin.Forms.Xaml.UnitTests", rootNs); Assert.AreEqual ("Xamarin.Forms.View", baseType.BaseType); - Assert.AreEqual (1, namesAndTypes.Count); - Assert.AreEqual ("label0", namesAndTypes.First().Key); - Assert.AreEqual ("Xamarin.Forms.Label", namesAndTypes.First().Value.BaseType); + Assert.AreEqual (1, codeMemberFields.Count()); + Assert.AreEqual ("label0", codeMemberFields.First().Name); + Assert.AreEqual ("Xamarin.Forms.Label", codeMemberFields.First().Type.BaseType); } [Test] @@ -92,13 +92,12 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; - - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); - Assert.AreEqual (1, namesAndTypes.Count); - Assert.AreEqual ("listView", namesAndTypes.First ().Key); - Assert.AreEqual ("CustomListViewSample.CustomListView", namesAndTypes.First ().Value.BaseType); + IEnumerable<CodeMemberField> codeMemberFields; + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); + Assert.AreEqual (1, codeMemberFields.Count()); + Assert.AreEqual ("listView", codeMemberFields.First ().Name); + Assert.AreEqual ("CustomListViewSample.CustomListView", codeMemberFields.First ().Type.BaseType); } [Test] @@ -122,12 +121,12 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); - Assert.Contains ("included", namesAndTypes.Keys.ToList()); - Assert.False (namesAndTypes.Keys.Contains ("notincluded")); - Assert.AreEqual (1, namesAndTypes.Count); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); + Assert.Contains ("included", codeMemberFields.Select(cmf => cmf.Name).ToList()); + Assert.False (codeMemberFields.Select(cmf => cmf.Name).Contains ("notincluded")); + Assert.AreEqual (1, codeMemberFields.Count()); } [Test] @@ -152,11 +151,11 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); - Assert.False (namesAndTypes.Keys.Contains ("notincluded")); - Assert.AreEqual (0, namesAndTypes.Count); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); + Assert.False (codeMemberFields.Select(cmf => cmf.Name).Contains ("notincluded")); + Assert.AreEqual (0, codeMemberFields.Count()); } [Test] @@ -171,9 +170,9 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.AreEqual ("FooBar", rootType); Assert.AreEqual ("Xamarin.Forms.Foo`1", baseType.BaseType); Assert.AreEqual (1, baseType.TypeArguments.Count); @@ -192,9 +191,9 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.AreEqual ("FooBar", rootType); Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType); Assert.AreEqual (2, baseType.TypeArguments.Count); @@ -214,9 +213,9 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.AreEqual ("FooBar", rootType); Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType); Assert.AreEqual (2, baseType.TypeArguments.Count); @@ -239,9 +238,9 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.AreEqual ("FooBar", rootType); Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType); Assert.AreEqual (2, baseType.TypeArguments.Count); @@ -264,9 +263,9 @@ namespace Xamarin.Forms.Xaml.UnitTests var reader = new StringReader (xaml); string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.AreEqual ("FooBar", rootType); Assert.AreEqual ("Xamarin.Forms.Foo`2", baseType.BaseType); Assert.AreEqual (2, baseType.TypeArguments.Count); @@ -288,13 +287,40 @@ namespace Xamarin.Forms.Xaml.UnitTests using (var reader = new StringReader (xaml)) { string rootType, rootNs; CodeTypeReference baseType; - IDictionary<string,CodeTypeReference> namesAndTypes; + IEnumerable<CodeMemberField> codeMemberFields; - XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out namesAndTypes); + XamlGTask.ParseXaml (reader, out rootType, out rootNs, out baseType, out codeMemberFields); Assert.IsTrue (baseType.Options.HasFlag (CodeTypeReferenceOptions.GlobalReference)); - Assert.IsTrue (namesAndTypes.Values.First ().Options.HasFlag (CodeTypeReferenceOptions.GlobalReference)); + Assert.IsTrue (codeMemberFields.Select(cmf => cmf.Type).First ().Options.HasFlag (CodeTypeReferenceOptions.GlobalReference)); } } - } -} + [Test] + public void FieldModifier() + { + var xaml = @" + <ContentPage xmlns=""http://xamarin.com/schemas/2014/forms"" + xmlns:x=""http://schemas.microsoft.com/winfx/2009/xaml"" + xmlns:local=""clr-namespace:Xamarin.Forms.Xaml.UnitTests"" + x:Class=""Xamarin.Forms.Xaml.UnitTests.FieldModifier""> + <StackLayout> + <Label x:Name=""privateLabel"" /> + <Label x:Name=""internalLabel"" x:FieldModifier=""NotPublic"" /> + <Label x:Name=""publicLabel"" x:FieldModifier=""Public"" /> + </StackLayout> + </ContentPage>"; + + using (var reader = new StringReader(xaml)) + { + string rootType, rootNs; + CodeTypeReference baseType; + IEnumerable<CodeMemberField> codeMemberFields; + + XamlGTask.ParseXaml(reader, out rootType, out rootNs, out baseType, out codeMemberFields); + Assert.That(codeMemberFields.First(cmf => cmf.Name == "privateLabel").Attributes, Is.EqualTo(MemberAttributes.Private)); + Assert.That(codeMemberFields.First(cmf => cmf.Name == "internalLabel").Attributes, Is.EqualTo(MemberAttributes.Assembly)); + Assert.That(codeMemberFields.First(cmf => cmf.Name == "publicLabel").Attributes, Is.EqualTo(MemberAttributes.Public)); + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Xaml/XamlParser.cs b/Xamarin.Forms.Xaml/XamlParser.cs index eb078597..26936c98 100644 --- a/Xamarin.Forms.Xaml/XamlParser.cs +++ b/Xamarin.Forms.Xaml/XamlParser.cs @@ -213,12 +213,13 @@ namespace Xamarin.Forms.Xaml propertyName = XmlName.xName; break; case "x:Class": + case "x:FieldModifier": continue; default: Debug.WriteLine("Unhandled attribute {0}", reader.Name); continue; } - } + } if (reader.NamespaceURI == "http://schemas.microsoft.com/winfx/2009/xaml") { @@ -237,6 +238,7 @@ namespace Xamarin.Forms.Xaml propertyName = XmlName.xDataType; break; case "x:Class": + case "x:FieldModifier": continue; case "x:FactoryMethod": propertyName = XmlName.xFactoryMethod; |