diff --git a/Xamarin.Forms.Build.Tasks/BuildException.cs b/Xamarin.Forms.Build.Tasks/BuildException.cs index 706fabd240c..ab52966752e 100644 --- a/Xamarin.Forms.Build.Tasks/BuildException.cs +++ b/Xamarin.Forms.Build.Tasks/BuildException.cs @@ -88,6 +88,7 @@ class BuildExceptionCode public static BuildExceptionCode ResourceMissing = new BuildExceptionCode("XFC0124", nameof(ResourceMissing), ""); public static BuildExceptionCode ResourceDictDuplicateKey = new BuildExceptionCode("XFC0125", nameof(ResourceDictDuplicateKey), ""); public static BuildExceptionCode ResourceDictMissingKey = new BuildExceptionCode("XFC0126", nameof(ResourceDictMissingKey), ""); + public static BuildExceptionCode XKeyNotLiteral = new BuildExceptionCode("XFC0127", nameof(XKeyNotLiteral), ""); public string Code { get; private set; } public string ErrorMessageKey { get; private set; } diff --git a/Xamarin.Forms.Build.Tasks/ErrorMessages.Designer.cs b/Xamarin.Forms.Build.Tasks/ErrorMessages.Designer.cs index bbda8f5015b..e26a3aa9054 100644 --- a/Xamarin.Forms.Build.Tasks/ErrorMessages.Designer.cs +++ b/Xamarin.Forms.Build.Tasks/ErrorMessages.Designer.cs @@ -10,48 +10,35 @@ namespace Xamarin.Forms.Build.Tasks { using System; + using System.Reflection; - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class ErrorMessages { - private static global::System.Resources.ResourceManager resourceMan; + private static System.Resources.ResourceManager resourceMan; - private static global::System.Globalization.CultureInfo resourceCulture; + private static System.Globalization.CultureInfo resourceCulture; - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal ErrorMessages() { } - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Resources.ResourceManager ResourceManager { get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Xamarin.Forms.Build.Tasks.ErrorMessages", typeof(ErrorMessages).Assembly); + if (object.Equals(null, resourceMan)) { + System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Xamarin.Forms.Build.Tasks.ErrorMessages", typeof(ErrorMessages).Assembly); resourceMan = temp; } return resourceMan; } } - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] + internal static System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -60,319 +47,220 @@ internal ErrorMessages() { } } - /// - /// Looks up a localized string similar to No Add() method defined on "{0}{1}".. - /// internal static string AdderMissing { get { return ResourceManager.GetString("AdderMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Binding: Indexer did not contain arguments.. - /// internal static string BindingIndexerEmpty { get { return ResourceManager.GetString("BindingIndexerEmpty", resourceCulture); } } - /// - /// Looks up a localized string similar to Binding: Indexer did not contain closing bracket.. - /// internal static string BindingIndexerNotClosed { get { return ResourceManager.GetString("BindingIndexerNotClosed", resourceCulture); } } - /// - /// Looks up a localized string similar to Binding: "{0}" cannot be parsed as an index for a "{1}".. - /// internal static string BindingIndexerParse { get { return ResourceManager.GetString("BindingIndexerParse", resourceCulture); } } - /// - /// Looks up a localized string similar to Binding: Unsupported indexer index type: "{0}".. - /// internal static string BindingIndexerTypeUnsupported { get { return ResourceManager.GetString("BindingIndexerTypeUnsupported", resourceCulture); } } - /// - /// Looks up a localized string similar to Binding: Property "{0}" not found on "{1}".. - /// internal static string BindingPropertyNotFound { get { return ResourceManager.GetString("BindingPropertyNotFound", resourceCulture); } } - /// - /// Looks up a localized string similar to Missing a "public static Get{0}" method or a public instance property getter for the attached property "{1}.{0}Property".. - /// internal static string BPMissingGetter { get { return ResourceManager.GetString("BPMissingGetter", resourceCulture); } } - /// - /// Looks up a localized string similar to The name of the BindableProperty {0} does not end with "Property". - /// internal static string BPName { get { return ResourceManager.GetString("BPName", resourceCulture); } } - /// - /// Looks up a localized string similar to Missing default constructor for "{0}".. - /// internal static string ConstructorDefaultMissing { get { return ResourceManager.GetString("ConstructorDefaultMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Missing constructor for "{0}" with matching x:Arguments.. - /// internal static string ConstructorXArgsMissing { get { return ResourceManager.GetString("ConstructorXArgsMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Cannot set the content of "{0}" as it doesn't have a [ContentProperty] attribute.. - /// internal static string ContentPropertyAttributeMissing { get { return ResourceManager.GetString("ContentPropertyAttributeMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Cannot convert value "{0}" to "{1}".. - /// internal static string Conversion { get { return ResourceManager.GetString("Conversion", resourceCulture); } } - /// - /// Looks up a localized string similar to Enum value not found for "{0}".. - /// internal static string EnumValueMissing { get { return ResourceManager.GetString("EnumValueMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Invalid Xaml "{0}".. - /// internal static string InvalidXaml { get { return ResourceManager.GetString("InvalidXaml", resourceCulture); } } - /// - /// Looks up a localized string similar to Markup expression not closed.. - /// internal static string MarkupNotClosed { get { return ResourceManager.GetString("MarkupNotClosed", resourceCulture); } } - /// - /// Looks up a localized string similar to Error while parsing markup expression.. - /// internal static string MarkupParsingFailed { get { return ResourceManager.GetString("MarkupParsingFailed", resourceCulture); } } - /// - /// Looks up a localized string similar to No property, BindableProperty, or event found for "{0}", or mismatching type between value and property.. - /// internal static string MemberResolution { get { return ResourceManager.GetString("MemberResolution", resourceCulture); } } - /// - /// Looks up a localized string similar to No static method found for "{0}::{1} ({2})".. - /// internal static string MethodStaticMissing { get { return ResourceManager.GetString("MethodStaticMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to EventHandler "{0}" with correct signature not found in type "{1}".. - /// internal static string MissingEventHandler { get { return ResourceManager.GetString("MissingEventHandler", resourceCulture); } } - /// - /// Looks up a localized string similar to An element with the name "{0}" already exists in this NameScope.. - /// internal static string NamescopeDuplicate { get { return ResourceManager.GetString("NamescopeDuplicate", resourceCulture); } } - /// - /// Looks up a localized string similar to Missing mandatory property "{0}" on "{1}".. - /// internal static string PropertyMissing { get { return ResourceManager.GetString("PropertyMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Cannot resolve property "{0}" on type "{1} (property missing, or missing accessors)".. - /// internal static string PropertyResolution { get { return ResourceManager.GetString("PropertyResolution", resourceCulture); } } - /// - /// Looks up a localized string similar to "A resource with the key "{0}" is already present in the ResourceDictionary.. - /// internal static string ResourceDictDuplicateKey { get { return ResourceManager.GetString("ResourceDictDuplicateKey", resourceCulture); } } - /// - /// Looks up a localized string similar to Resources in ResourceDictionary require a x:Key attribute.. - /// internal static string ResourceDictMissingKey { get { return ResourceManager.GetString("ResourceDictMissingKey", resourceCulture); } } - /// - /// Looks up a localized string similar to Resource "{0}" not found.. - /// internal static string ResourceMissing { get { return ResourceManager.GetString("ResourceMissing", resourceCulture); } } - /// - /// Looks up a localized string similar to Multi-valued enums are not valid on sbyte enum types.. - /// internal static string SByteEnums { get { return ResourceManager.GetString("SByteEnums", resourceCulture); } } - /// - /// Looks up a localized string similar to StyleSheet require either a Source or a content.. - /// internal static string StyleSheetNoSourceOrContent { get { return ResourceManager.GetString("StyleSheetNoSourceOrContent", resourceCulture); } } - /// - /// Looks up a localized string similar to Source property is not a string literal.. - /// internal static string StyleSheetSourceNotALiteral { get { return ResourceManager.GetString("StyleSheetSourceNotALiteral", resourceCulture); } } - /// - /// Looks up a localized string similar to StyleSheet can not have both a Source and a content.. - /// internal static string StyleSheetSourceOrContent { get { return ResourceManager.GetString("StyleSheetSourceOrContent", resourceCulture); } } - /// - /// Looks up a localized string similar to Style property or Content is not a string literal.. - /// internal static string StyleSheetStyleNotALiteral { get { return ResourceManager.GetString("StyleSheetStyleNotALiteral", resourceCulture); } } - /// - /// Looks up a localized string similar to Cannot resolve type "{0}".. - /// internal static string TypeResolution { get { return ResourceManager.GetString("TypeResolution", resourceCulture); } } - /// - /// Looks up a localized string similar to x:DataType expects a string literal, an {{x:Type}} markup or {{x:Nul}l}.. - /// internal static string XDataTypeSyntax { get { return ResourceManager.GetString("XDataTypeSyntax", resourceCulture); } } - /// - /// Looks up a localized string similar to Undeclared xmlns prefix "{0}".. - /// internal static string XmlnsUndeclared { get { return ResourceManager.GetString("XmlnsUndeclared", resourceCulture); } } - /// - /// Looks up a localized string similar to x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}".. - /// internal static string XStaticResolution { get { return ResourceManager.GetString("XStaticResolution", resourceCulture); } } - /// - /// Looks up a localized string similar to Syntax for x:Static is "[Member=][prefix:]typeName.staticMemberName".. - /// internal static string XStaticSyntax { get { return ResourceManager.GetString("XStaticSyntax", resourceCulture); } } + + internal static string XKeyNotLiteral { + get { + return ResourceManager.GetString("XKeyNotLiteral", resourceCulture); + } + } } } diff --git a/Xamarin.Forms.Build.Tasks/ErrorMessages.resx b/Xamarin.Forms.Build.Tasks/ErrorMessages.resx index 568464e4d9a..b127c2cb14f 100644 --- a/Xamarin.Forms.Build.Tasks/ErrorMessages.resx +++ b/Xamarin.Forms.Build.Tasks/ErrorMessages.resx @@ -244,5 +244,9 @@ Syntax for x:Static is "[Member=][prefix:]typeName.staticMemberName". + + + x:Key expects a string literal. + \ No newline at end of file diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs index 78725effbf0..9a8883187f3 100644 --- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs +++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs @@ -1429,7 +1429,8 @@ static bool CanAddToResourceDictionary(VariableDefinition parent, TypeReference if (node.Properties.ContainsKey(XmlName.xKey)) { - var key = (node.Properties[XmlName.xKey] as ValueNode).Value as string; + var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null); + var key = (valueNode).Value as string; if (!resourceNamesInUse.TryGetValue(parent, out var names)) resourceNamesInUse[parent] = (names = new List()); if (names.Contains(key)) @@ -1482,7 +1483,8 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren if (node.Properties.ContainsKey(XmlName.xKey)) { var names = resourceNamesInUse[parent]; - var key = (node.Properties[XmlName.xKey] as ValueNode).Value as string; + var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null); + var key = (valueNode).Value as string; names.Add(key); // IL_0014: ldstr "key" diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.cs.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.cs.xlf index 2e0f63ff566..7cbd7bf8dcc 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.cs.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.cs.xlf @@ -162,6 +162,11 @@ x:DataType očekává řetězcový literál, značku {{x:Type}} nebo {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: nejde najít veřejné nebo přístupné interní statické pole, statickou vlastnost, konstantu nebo hodnotu výčtu s názvem {0} v typu {1}. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.de.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.de.xlf index b07ac7bd8d4..56eac6f37c1 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.de.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.de.xlf @@ -162,6 +162,11 @@ x:DataType erwartet ein Zeichenfolgenliteral, ein {{x:Type}}-Markup oder {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: Ein öffentliches – oder zugängliches internes – statisches Feld, eine statische Eigenschaft oder ein const- oder enum-Wert mit dem Namen "{0}" wurde in "{1}" nicht gefunden. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.es.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.es.xlf index 54f4aae7f6d..d015bba319d 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.es.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.es.xlf @@ -162,6 +162,11 @@ x:DataType espera un literal de cadena, una marca {{x:Type}} o {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: no puede encontrar un campo estático público (o interno accesible), una propiedad estática o un valor constante o de enumeración llamados "{0}" en "{1}". diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.fr.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.fr.xlf index 5ee01736932..dd6e4350143 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.fr.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.fr.xlf @@ -162,6 +162,11 @@ x:DataType attend un littéral de chaîne, une balise {{x:Type}} ou {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static : impossible de localiser un champ statique public (ou interne et accessible), une propriété statique, une valeur const ou une valeur enum portant le nom "{0}" dans "{1}". diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.it.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.it.xlf index 8c806d9e7ee..c4380946866 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.it.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.it.xlf @@ -162,6 +162,11 @@ Con x:DataType è previsto un valore letterale stringa, un markup {{x:Type}} oppure {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: non è possibile trovare un valore di campo statico pubblico o interno accessibile, di proprietà statica, di costante o di enumerazione denominato "{0}" in "{1}". diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ja.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ja.xlf index 6df19ec3c48..6cb313abae9 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ja.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ja.xlf @@ -162,6 +162,11 @@ x:DataType には、文字列リテラル、{{x:Type}} マークアップ、または {{x:Nul}l} を指定する必要があります。 + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: "{1}" に、"{0}" という名前のパブリックな (またはアクセス可能な内部の) 静的フィールド、静的プロパティ、const、または列挙値が見つかりません。 diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ko.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ko.xlf index c372adc185b..91d664cd0a0 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ko.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ko.xlf @@ -162,6 +162,11 @@ x:DataType에는 {{x:Type}} 태그 또는 {{x:Nul}l} 문자열 리터럴이 필요합니다. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: "{1}"에서 이름이 "{0}"인 public 또는 액세스 가능한 내부 정적 필드, 정적 속성, 상수 또는 열거형 값을 찾을 수 없습니다. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pl.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pl.xlf index 6d7459fea77..d20887f84b4 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pl.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pl.xlf @@ -162,6 +162,11 @@ Argument x:DataType oczekuje literału ciągu, znacznika {{x:Type}} lub {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: nie można odnaleźć publicznego — lub dostępnego wewnętrznie — pola statycznego, właściwości statycznej, stałej lub wartości wyliczenia o nazwie „{0}” w typie „{1}”. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pt-BR.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pt-BR.xlf index d25512046e9..a3d8e626569 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pt-BR.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.pt-BR.xlf @@ -162,6 +162,11 @@ O x:DataType espera um literal de cadeia de caracteres, uma marcação {{x:Type}} ou um {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". O x:Static: não pôde encontrar um campo estático, uma propriedade estática, um valor const ou enumerado público (ou interno acessível) denominado "{0}" em "{1}". diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ru.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ru.xlf index e8b7c0eab7f..a556605f7e0 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ru.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.ru.xlf @@ -162,6 +162,11 @@ x:DataType ожидает строковый литерал, разметку {{x:Type}} или {{x:Nul}l}. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: не удается найти статическое поле, статическое свойство, константу или значение перечисления с именем "{0}" в "{1}", которые являлись бы открытыми или были бы доступны внутренне. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.tr.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.tr.xlf index 05731f2fa0c..e1eca33056a 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.tr.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.tr.xlf @@ -162,6 +162,11 @@ x:DataType için bir dize sabit değeri, {{x:Type}} işaretlemesi veya {{x:Nul}l} bekleniyor. + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: "{1}" içinde "{0}" adlı genel -- veya erişilebilir, dahili -- statik alan, statik özellik, sabit veya sabit listesi değeri bulunamıyor. diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf index 13105c7dc9d..0ed5bcfa322 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hans.xlf @@ -162,6 +162,11 @@ x:DataType 需要字符串文本、{{x:Type}} 标记或 {{x:Nul}l}。 + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: 在“{1}”中找不到公共(或可访问的内部)静态字段、静态属性、常量或枚举值“{0}”。 diff --git a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf index 7845a86ca7f..38e5bd1dc7f 100644 --- a/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf +++ b/Xamarin.Forms.Build.Tasks/xlf/ErrorMessages.zh-Hant.xlf @@ -162,6 +162,11 @@ x:DataType 需要字串常值、{{x:Type}} 標記或 {{x:Nul}l}。 + + x:Key expects a string literal. + x:Key expects a string literal. + + x:Static: unable to find a public -- or accessible internal -- static field, static property, const or enum value named "{0}" in "{1}". x:Static: 在 "{1}" 中找不到名為 "{0}" 的公用 (或可存取內部) 靜態欄位、靜態屬性、常數或列舉值。 diff --git a/Xamarin.Forms.Xaml.UnitTests/SetStyleIdFromXName.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/SetStyleIdFromXName.xaml.cs index a8757942869..5428111ff1d 100644 --- a/Xamarin.Forms.Xaml.UnitTests/SetStyleIdFromXName.xaml.cs +++ b/Xamarin.Forms.Xaml.UnitTests/SetStyleIdFromXName.xaml.cs @@ -6,11 +6,7 @@ namespace Xamarin.Forms.Xaml.UnitTests { public partial class SetStyleIdFromXName : ContentPage { - public SetStyleIdFromXName() - { - InitializeComponent(); - } - + public SetStyleIdFromXName() => InitializeComponent(); public SetStyleIdFromXName(bool useCompiledXaml) { //this stub will be replaced at compile time @@ -19,17 +15,8 @@ public SetStyleIdFromXName(bool useCompiledXaml) [TestFixture] public class Tests { - [SetUp] - public void Setup() - { - Device.PlatformServices = new MockPlatformServices(); - } - - [TearDown] - public void TearDown() - { - Device.PlatformServices = null; - } + [SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices(); + [TearDown] public void TearDown() => Device.PlatformServices = null; [TestCase(false), TestCase(true)] public void SetStyleId(bool useCompiledXaml) diff --git a/Xamarin.Forms.Xaml.UnitTests/XStaticException.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XStaticException.xaml.cs index 5cb02a119ff..952444f9388 100644 --- a/Xamarin.Forms.Xaml.UnitTests/XStaticException.xaml.cs +++ b/Xamarin.Forms.Xaml.UnitTests/XStaticException.xaml.cs @@ -29,23 +29,8 @@ public class Tests // - An enumeration value // All other cases should throw - [SetUp] - public void Setup() - { - Device.PlatformServices = new MockPlatformServices(); - - //there's a test not resetting the values correctly, but can't find which one... -#pragma warning disable 0618 - Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null; - Xamarin.Forms.Xaml.Internals.XamlLoader.DoNotThrowOnExceptions = false; -#pragma warning restore 0618 - } - - [TearDown] - public void TearDown() - { - Device.PlatformServices = null; - } + [SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices(); + [TearDown] public void TearDown() => Device.PlatformServices = null; [TestCase(false)] [TestCase(true)] diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlLoaderGetXamlForTypeTests.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XamlLoaderGetXamlForTypeTests.xaml.cs index 2aca4333d17..1cc93a5b0f7 100644 --- a/Xamarin.Forms.Xaml.UnitTests/XamlLoaderGetXamlForTypeTests.xaml.cs +++ b/Xamarin.Forms.Xaml.UnitTests/XamlLoaderGetXamlForTypeTests.xaml.cs @@ -30,6 +30,20 @@ public void SetUp() #pragma warning restore 0618 } + [TearDown] + public void TearDown() + { + Device.PlatformServices = null; + XamlLoader.FallbackTypeResolver = null; + XamlLoader.ValueCreatedCallback = null; + XamlLoader.InstantiationFailedCallback = null; +#pragma warning disable 0618 + Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null; + Xamarin.Forms.Xaml.Internals.XamlLoader.DoNotThrowOnExceptions = false; +#pragma warning restore 0618 + + } + [TestCase(false)] [TestCase(true)] public void XamlContentIsReplaced(bool useCompiledXaml) diff --git a/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml b/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml new file mode 100644 index 00000000000..b04b1a940aa --- /dev/null +++ b/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml @@ -0,0 +1,8 @@ + + + + + #96d1ff + + + diff --git a/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml.cs new file mode 100644 index 00000000000..3c924f6f298 --- /dev/null +++ b/Xamarin.Forms.Xaml.UnitTests/xKeyLiteral.xaml.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +using System; +using System.Collections.Generic; +using NUnit.Framework; +using Xamarin.Forms; +using Xamarin.Forms.Build.Tasks; +using Xamarin.Forms.Core.UnitTests; + +namespace Xamarin.Forms.Xaml.UnitTests +{ + [XamlCompilation(XamlCompilationOptions.Skip)] + public partial class xKeyLiteral : ContentPage + { + public xKeyLiteral() => InitializeComponent(); + public xKeyLiteral(bool useCompiledXaml) + { + //this stub will be replaced at compile time + } + + [TestFixture] + class Tests + { + [SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices(); + [TearDown] public void TearDown() => Device.PlatformServices = null; + + [Test] + //this requirement might change, see https://github.com/xamarin/Xamarin.Forms/issues/12425 + public void xKeyRequireStringLiteral([Values(false, true)] bool useCompiledXaml) + { + if (useCompiledXaml) + Assert.Throws(() => MockCompiler.Compile(typeof(xKeyLiteral))); + else + Assert.Throws(() => new xKeyLiteral(useCompiledXaml)); + } + } + } +} diff --git a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs index 0e451f029bc..b580103c2f1 100644 --- a/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs +++ b/Xamarin.Forms.Xaml/ApplyPropertiesVisitor.cs @@ -46,9 +46,8 @@ public void Visit(ValueNode node, INode parentNode) if (!Values.TryGetValue(parentNode, out var source) && Context.ExceptionHandler != null) return; - XmlName propertyName; - if (TryGetPropertyName(node, parentNode, out propertyName)) + if (TryGetPropertyName(node, parentNode, out XmlName propertyName)) { if (TrySetRuntimeName(propertyName, source, value, node)) return; @@ -82,8 +81,7 @@ public void Visit(MarkupNode node, INode parentNode) public void Visit(ElementNode node, INode parentNode) { - XmlName propertyName; - if (TryGetPropertyName(node, parentNode, out propertyName) && propertyName == XmlName._CreateContent) + if (TryGetPropertyName(node, parentNode, out XmlName propertyName) && propertyName == XmlName._CreateContent) { var s0 = Values[parentNode]; if (s0 is ElementTemplate) @@ -97,8 +95,7 @@ public void Visit(ElementNode node, INode parentNode) propertyName = XmlName.Empty; //Simplify ListNodes with single elements - var pList = parentNode as ListNode; - if (pList != null && pList.CollectionItems.Count == 1) + if (parentNode is ListNode pList && pList.CollectionItems.Count == 1) { propertyName = pList.XmlName; parentNode = parentNode.Parent; @@ -127,7 +124,15 @@ public void Visit(ElementNode node, INode parentNode) ProvideValue(ref value, node, source, XmlName.Empty); string contentProperty; Exception xpe = null; - var xKey = node.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)node.Properties[XmlName.xKey]).Value as string : null; + + string xKey = null; + if (xpe == null && node.Properties.ContainsKey(XmlName.xKey)) + { + if ((node.Properties[XmlName.xKey] is ValueNode valueNode)) + xKey = valueNode.Value as string; + if (xKey == null) + xpe = new XamlParseException("x:Key expects a string literal.", node as IXmlLineInfo); + } //ResourceDictionary if (xpe == null && TryAddToResourceDictionary(source as ResourceDictionary, value, xKey, node, out xpe)) @@ -168,10 +173,17 @@ public void Visit(ElementNode node, INode parentNode) if (Skips.Contains(parentList.XmlName)) return; Exception xpe = null; - var xKey = node.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)node.Properties[XmlName.xKey]).Value as string : null; + string xKey = null; + if (xpe == null && node.Properties.ContainsKey(XmlName.xKey)) + { + if ((node.Properties[XmlName.xKey] is ValueNode valueNode)) + xKey = valueNode.Value as string; + if (xKey == null) + xpe = new XamlParseException("x:Key expects a string literal.", node as IXmlLineInfo); + } var collection = GetPropertyValue(source, parentList.XmlName, Context.RootElement, parentList, out _, out _) as IEnumerable; - if (collection == null) + if (xpe == null && collection == null) xpe = new XamlParseException($"Property {parentList.XmlName.LocalName} is null or is not IEnumerable", node); if (xpe == null && TryAddToResourceDictionary(collection as ResourceDictionary, value, xKey, node, out xpe)) diff --git a/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs index 7ee5c389e54..7a03fc48831 100644 --- a/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs +++ b/Xamarin.Forms.Xaml/FillResourceDictionariesVisitor.cs @@ -8,10 +8,7 @@ namespace Xamarin.Forms.Xaml { class FillResourceDictionariesVisitor : IXamlNodeVisitor { - public FillResourceDictionariesVisitor(HydrationContext context) - { - Context = context; - } + public FillResourceDictionariesVisitor(HydrationContext context) => Context = context; HydrationContext Context { get; } Dictionary Values => Context.Values; @@ -53,12 +50,12 @@ public void Visit(ElementNode node, INode parentNode) } //Only proceed further if the node is a keyless RD - if (parentNode is IElementNode + if ( parentNode is IElementNode && Context.Types.TryGetValue((IElementNode)parentNode, out var parentType) && typeof(ResourceDictionary).IsAssignableFrom(parentType) && !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey)) node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode); - else if (parentNode is ListNode + else if ( parentNode is ListNode && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)]) && !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey)) node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode); @@ -74,15 +71,14 @@ public void Visit(ListNode node, INode parentNode) public bool SkipChildren(INode node, INode parentNode) { - var enode = node as ElementNode; - if (enode is null) + if (!(node is ElementNode)) return false; - if (parentNode is IElementNode + if ( parentNode is IElementNode && Context.Types.TryGetValue((IElementNode)parentNode, out var parentType) && typeof(ResourceDictionary).IsAssignableFrom(parentType) && !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey)) return true; - if (parentNode is ListNode + if ( parentNode is ListNode && typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode.Parent)]) && !((IElementNode)parentNode.Parent).Properties.ContainsKey(XmlName.xKey)) return true;