зеркало из https://github.com/DeGsoft/maui-linux.git
Reverts "[Xaml] require escaping curly braces (#4723)" and "[X] only require escaping if starts with '{' (#5169)" (#5424)
* Revert "[X] only require escaping if starts with '{' (#5169)" This reverts commitcd73391c3a
. * Revert "[Xaml] require escaping curly braces (#4723)" This reverts commit6753ace40e
. * Make sure parsing doesn't fail when there *are* curly braces now
This commit is contained in:
Родитель
a101758f71
Коммит
d8f0c308a7
|
@ -20,7 +20,7 @@
|
|||
<StackLayout>
|
||||
<Label FontAttributes="Bold" FontSize="18" Margin="10,25,10,10"
|
||||
HorizontalOptions="Fill" HorizontalTextAlignment="Center"
|
||||
Text="{Binding Filter, StringFormat='{}Your filter term of {0} did not match any records'}"></Label>
|
||||
Text="{Binding Filter, StringFormat='Your filter term of {0} did not match any records'}"></Label>
|
||||
</StackLayout>
|
||||
</DataTemplate>
|
||||
</CollectionView.EmptyViewTemplate>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?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.Gh2756">
|
||||
<StackLayout>
|
||||
<Label Text="{Binding Color.R, StringFormat='R = {0:F2}'}"/> <!-- should parse -->
|
||||
<Label Text="{Binding Path=StartTime, StringFormat='{0:yy-MM-dd}'}"/> <!-- should throw -->
|
||||
</StackLayout>
|
||||
</ContentPage>
|
|
@ -1,34 +0,0 @@
|
|||
using NUnit.Framework;
|
||||
|
||||
using Xamarin.Forms.Core.UnitTests;
|
||||
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Xamarin.Forms.Xaml.UnitTests
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Skip)]
|
||||
public partial class Gh2756 : ContentPage
|
||||
{
|
||||
public Gh2756() => InitializeComponent();
|
||||
public Gh2756(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]
|
||||
public void UnescapedBraces([Values(false, true)]bool useCompiledXaml)
|
||||
{
|
||||
if (useCompiledXaml)
|
||||
Assert.Throws(new XamlParseExceptionConstraint(8, 16), () => MockCompiler.Compile(typeof(Gh2756)));
|
||||
else
|
||||
Assert.Throws(new XamlParseExceptionConstraint(8, 16), () => new Gh2756(useCompiledXaml));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<?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.Issue1438">
|
||||
|
|
|
@ -82,7 +82,7 @@ xmlns=""http://xamarin.com/schemas/2014/forms""
|
|||
<local:SeverityColorConverter x:Key=""SeverityColorConverter"" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<Label Text=""{Binding value, StringFormat='{}{0}'}""
|
||||
<Label Text=""{Binding value, StringFormat='{0}'}""
|
||||
WidthRequest=""50""
|
||||
TextColor=""Black""
|
||||
x:Name=""label""
|
||||
|
@ -97,6 +97,35 @@ xmlns=""http://xamarin.com/schemas/2014/forms""
|
|||
Assert.AreEqual (1, SeverityColorConverter.count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConverterIsInvoked_Escaped()
|
||||
{
|
||||
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;assembly=Xamarin.Forms.Xaml.UnitTests"">
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<local:SeverityColorConverter x:Key=""SeverityColorConverter"" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<Label Text=""{Binding value, StringFormat='{}{0}'}""
|
||||
WidthRequest=""50""
|
||||
TextColor=""Black""
|
||||
x:Name=""label""
|
||||
BackgroundColor=""{Binding Severity, Converter={StaticResource SeverityColorConverter}}""
|
||||
XAlign=""Center"" YAlign=""Center""/>
|
||||
</ContentPage>";
|
||||
|
||||
var layout = new ContentPage().LoadFromXaml(xaml);
|
||||
layout.BindingContext = new { Value = "Foo", Severity = "Bar" };
|
||||
var label = layout.FindByName<Label>("label");
|
||||
Assert.AreEqual(Color.Blue, label.BackgroundColor);
|
||||
Assert.AreEqual(1, SeverityColorConverter.count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ResourcesInNonXFBaseClassesAreFound ()
|
||||
{
|
||||
|
|
|
@ -248,25 +248,17 @@ namespace Xamarin.Forms.Xaml.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void NonStartingBracesDoNotNeedToBeEscaped()
|
||||
public void BindingStringFormatWithoutEscaping ()
|
||||
{
|
||||
var bindingString = "{Binding Foo, StringFormat='Hello {0}'}";
|
||||
var bindingString = "{Binding Foo, StringFormat='{0,20}'}";
|
||||
|
||||
Assert.DoesNotThrow(() => new MarkupExtensionParser().ParseExpression(ref bindingString, new Internals.XamlServiceProvider(null, null)
|
||||
{
|
||||
var binding = (new MarkupExtensionParser ()).ParseExpression (ref bindingString, new Internals.XamlServiceProvider (null, null) {
|
||||
IXamlTypeResolver = typeResolver,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void BracesNeedsToBeEscaped2()
|
||||
{
|
||||
var bindingString = "{Binding Foo, StringFormat='{0}'}";
|
||||
|
||||
Assert.Throws<XamlParseException>(() => new MarkupExtensionParser().ParseExpression(ref bindingString, new Internals.XamlServiceProvider(null, null)
|
||||
{
|
||||
IXamlTypeResolver = typeResolver,
|
||||
}));
|
||||
Assert.That (binding, Is.InstanceOf<Binding> ());
|
||||
Assert.AreEqual ("Foo", ((Binding)binding).Path);
|
||||
Assert.AreEqual ("{0,20}", ((Binding)binding).StringFormat);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -46,10 +46,7 @@ namespace Xamarin.Forms.Xaml
|
|||
return expression.Substring(2);
|
||||
|
||||
if (expression[expression.Length - 1] != '}')
|
||||
{
|
||||
var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider != null) ? (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider).XmlLineInfo : new XmlLineInfo();
|
||||
throw new XamlParseException("Expression must end with '}'", lineInfo);
|
||||
}
|
||||
throw new Exception("Expression must end with '}'");
|
||||
|
||||
int len;
|
||||
string match;
|
||||
|
@ -117,6 +114,7 @@ namespace Xamarin.Forms.Xaml
|
|||
|
||||
protected void HandleProperty(string prop, IServiceProvider serviceProvider, ref string remaining, bool isImplicit)
|
||||
{
|
||||
char next;
|
||||
object value = null;
|
||||
string str_value;
|
||||
|
||||
|
@ -139,13 +137,7 @@ namespace Xamarin.Forms.Xaml
|
|||
str_value = value as string;
|
||||
}
|
||||
else
|
||||
str_value = GetNextPiece(ref remaining, out var next);
|
||||
|
||||
if (str_value != null && !str_value.StartsWith("{}", StringComparison.Ordinal) && str_value.Length > 2 && str_value.StartsWith("{", StringComparison.Ordinal))
|
||||
{
|
||||
var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider != null) ? (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) as IXmlLineInfoProvider).XmlLineInfo : new XmlLineInfo();
|
||||
throw new XamlParseException("Strings starting with `{` needs to be escaped. Start the string with `{}`", lineInfo);
|
||||
}
|
||||
str_value = GetNextPiece(ref remaining, out next);
|
||||
|
||||
SetPropertyValue(prop, str_value, value, serviceProvider);
|
||||
}
|
||||
|
|
|
@ -5,31 +5,27 @@ namespace Xamarin.Forms.Xaml
|
|||
{
|
||||
internal sealed class MarkupExtensionParser : MarkupExpressionParser, IExpressionParser<object>
|
||||
{
|
||||
IMarkupExtension _markupExtension;
|
||||
IMarkupExtension markupExtension;
|
||||
|
||||
public object Parse(string match, ref string remaining, IServiceProvider serviceProvider)
|
||||
{
|
||||
var typeResolver = serviceProvider.GetService(typeof (IXamlTypeResolver)) as IXamlTypeResolver;
|
||||
switch (match) {
|
||||
case "Binding":
|
||||
_markupExtension = new BindingExtension();
|
||||
break;
|
||||
case "TemplateBinding":
|
||||
_markupExtension = new TemplateBindingExtension();
|
||||
break;
|
||||
case "StaticResource":
|
||||
_markupExtension = new StaticResourceExtension();
|
||||
break;
|
||||
case "OnPlatform":
|
||||
_markupExtension = new OnPlatformExtension();
|
||||
break;
|
||||
case "OnIdiom":
|
||||
_markupExtension = new OnIdiomExtension();
|
||||
break;
|
||||
case "DataTemplate":
|
||||
_markupExtension = new DataTemplateExtension();
|
||||
break;
|
||||
default:
|
||||
|
||||
//shortcut for Binding and StaticResource, to avoid too many reflection calls.
|
||||
if (match == "Binding")
|
||||
markupExtension = new BindingExtension();
|
||||
else if (match == "TemplateBinding")
|
||||
markupExtension = new TemplateBindingExtension();
|
||||
else if (match == "StaticResource")
|
||||
markupExtension = new StaticResourceExtension();
|
||||
else if (match == "OnPlatform")
|
||||
markupExtension = new OnPlatformExtension();
|
||||
else if (match == "OnIdiom")
|
||||
markupExtension = new OnIdiomExtension();
|
||||
else if (match == "DataTemplate")
|
||||
markupExtension = new DataTemplateExtension();
|
||||
else
|
||||
{
|
||||
if (typeResolver == null)
|
||||
return null;
|
||||
Type type;
|
||||
|
@ -37,21 +33,20 @@ namespace Xamarin.Forms.Xaml
|
|||
//The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
|
||||
if (!typeResolver.TryResolve(match + "Extension", out type) && !typeResolver.TryResolve(match, out type))
|
||||
throw new XamlParseException($"MarkupExtension not found for {match}", serviceProvider);
|
||||
_markupExtension = Activator.CreateInstance(type) as IMarkupExtension;
|
||||
break;
|
||||
markupExtension = Activator.CreateInstance(type) as IMarkupExtension;
|
||||
}
|
||||
|
||||
if (_markupExtension == null)
|
||||
if (markupExtension == null)
|
||||
throw new XamlParseException($"Missing public default constructor for MarkupExtension {match}", serviceProvider);
|
||||
|
||||
if (remaining == "}")
|
||||
return _markupExtension.ProvideValue(serviceProvider);
|
||||
return markupExtension.ProvideValue(serviceProvider);
|
||||
|
||||
string piece;
|
||||
while ((piece = GetNextPiece(ref remaining, out char next)) != null)
|
||||
HandleProperty(piece, serviceProvider, ref remaining, next != '=');
|
||||
|
||||
return _markupExtension.ProvideValue(serviceProvider);
|
||||
return markupExtension.ProvideValue(serviceProvider);
|
||||
}
|
||||
|
||||
protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
|
||||
|
@ -59,7 +54,7 @@ namespace Xamarin.Forms.Xaml
|
|||
MethodInfo setter;
|
||||
if (prop == null) {
|
||||
//implicit property
|
||||
var t = _markupExtension.GetType();
|
||||
var t = markupExtension.GetType();
|
||||
prop = ApplyPropertiesVisitor.GetContentPropertyName(t.GetTypeInfo());
|
||||
if (prop == null)
|
||||
return;
|
||||
|
@ -72,26 +67,26 @@ namespace Xamarin.Forms.Xaml
|
|||
}
|
||||
else {
|
||||
try {
|
||||
setter = _markupExtension.GetType().GetRuntimeProperty(prop).SetMethod;
|
||||
setter = markupExtension.GetType().GetRuntimeProperty(prop).SetMethod;
|
||||
}
|
||||
catch (AmbiguousMatchException e) {
|
||||
throw new XamlParseException($"Multiple properties with name '{_markupExtension.GetType()}.{prop}' found.", serviceProvider, innerException: e);
|
||||
throw new XamlParseException($"Multiple properties with name '{markupExtension.GetType()}.{prop}' found.", serviceProvider, innerException: e);
|
||||
}
|
||||
|
||||
}
|
||||
if (value == null && strValue != null) {
|
||||
try {
|
||||
value = strValue.ConvertTo(_markupExtension.GetType().GetRuntimeProperty(prop).PropertyType,
|
||||
value = strValue.ConvertTo(markupExtension.GetType().GetRuntimeProperty(prop).PropertyType,
|
||||
(Func<TypeConverter>)null, serviceProvider, out Exception converterException);
|
||||
if (converterException != null)
|
||||
throw converterException;
|
||||
}
|
||||
catch (AmbiguousMatchException e) {
|
||||
throw new XamlParseException($"Multiple properties with name '{_markupExtension.GetType()}.{prop}' found.", serviceProvider, innerException: e);
|
||||
throw new XamlParseException($"Multiple properties with name '{markupExtension.GetType()}.{prop}' found.", serviceProvider, innerException: e);
|
||||
}
|
||||
}
|
||||
|
||||
setter.Invoke(_markupExtension, new[] { value });
|
||||
setter.Invoke(markupExtension, new[] { value });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче