[previewer] resilience on createvalue (#5369)

- fixes #5171
This commit is contained in:
Stephane Delcroix 2019-02-26 20:09:16 +01:00 коммит произвёл GitHub
Родитель a6c08d577e
Коммит af99e177d7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 51 добавлений и 17 удалений

Просмотреть файл

@ -51,7 +51,7 @@ namespace Xamarin.Forms.Xaml.UnitTests
}
[Test]
public void ContentPageWithMissingType()
public void ContentPageWithMissingTypeMockviewReplacement()
{
XamlLoader.FallbackTypeResolver = (p, type) => type ?? typeof(MockView);
@ -68,6 +68,28 @@ namespace Xamarin.Forms.Xaml.UnitTests
Assert.That(page.Content, Is.TypeOf<MockView>());
}
[Test]
public void ContentPageWithMissingTypeNoReplacement()
{
XamlLoader.FallbackTypeResolver = (p, type) => type;
var xaml = @"
<ContentPage xmlns=""http://xamarin.com/schemas/2014/forms""
xmlns:local=""clr-namespace:MissingNamespace;assembly=MissingAssembly""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<ContentPage.Content>
<local:MyCustomButton Foo=""Bar"">
<local:MyCustomButton.Qux>
<Label />
</local:MyCustomButton.Qux>
</local:MyCustomButton>
</ContentPage.Content>
</ContentPage>";
var page = (ContentPage)XamlLoader.Create(xaml, true);
Assert.That(page.Content, Is.Null);
}
[Test]
public void MissingTypeWithKnownProperty()
{

Просмотреть файл

@ -36,13 +36,15 @@ namespace Xamarin.Forms.Xaml
public bool StopOnResourceDictionary { get; }
public bool VisitNodeOnDataTemplate => true;
public bool SkipChildren(INode node, INode parentNode) => false;
public bool IsResourceDictionary(ElementNode node) => typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]);
public bool IsResourceDictionary(ElementNode node) => Context.Types.TryGetValue(node, out var type) && typeof(ResourceDictionary).IsAssignableFrom(type);
public void Visit(ValueNode node, INode parentNode)
{
var parentElement = parentNode as IElementNode;
var value = Values [node];
var source = Values [parentNode];
if (!Values.TryGetValue(parentNode, out var source) && Context.ExceptionHandler != null)
return;
XmlName propertyName;
if (TryGetPropertyName(node, parentNode, out propertyName)) {
@ -95,7 +97,8 @@ namespace Xamarin.Forms.Xaml
parentElement = parentNode as IElementNode;
}
var value = Values[node];
if (!Values.TryGetValue(node, out var value) && Context.ExceptionHandler != null)
return;
if (propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) {
if (Skips.Contains(propertyName))
@ -103,12 +106,14 @@ namespace Xamarin.Forms.Xaml
if (parentElement.SkipProperties.Contains(propertyName))
return;
var source = Values[parentNode];
if (!Values.TryGetValue(parentNode, out var source) && Context.ExceptionHandler != null)
return;
ProvideValue(ref value, node, source, propertyName);
SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node);
}
else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) {
var source = Values[parentNode];
if (!Values.TryGetValue(parentNode, out var source) && Context.ExceptionHandler != null)
return;
ProvideValue(ref value, node, source, XmlName.Empty);
string contentProperty;
Exception xpe = null;
@ -143,7 +148,8 @@ namespace Xamarin.Forms.Xaml
throw xpe;
}
else if (IsCollectionItem(node, parentNode) && parentNode is ListNode) {
var source = Values[parentNode.Parent];
if (!Values.TryGetValue(parentNode.Parent, out var source) && Context.ExceptionHandler != null)
return;
ProvideValue(ref value, node, source, XmlName.Empty);
var parentList = (ListNode)parentNode;
if (Skips.Contains(parentList.XmlName))

Просмотреть файл

@ -43,12 +43,15 @@ namespace Xamarin.Forms.Xaml
{
object value = null;
XamlParseException xpe;
var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement?.GetType().GetTypeInfo().Assembly,
out xpe);
if (xpe != null)
out XamlParseException xpe);
if (xpe != null) {
if (Context.ExceptionHandler != null) {
Context.ExceptionHandler(xpe);
return;
}
throw xpe;
}
Context.Types[node] = type;
if (IsXaml2009LanguagePrimitive(node))
value = CreateLanguagePrimitive(type, node);

Просмотреть файл

@ -25,7 +25,7 @@ namespace Xamarin.Forms.Xaml
public void Visit(ValueNode node, INode parentNode)
{
if (!typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)]))
if (!Context.Types.TryGetValue((IElementNode)parentNode, out var type) || !typeof(ResourceDictionary).IsAssignableFrom(type))
return;
node.Accept(new ApplyPropertiesVisitor(Context, stopOnResourceDictionary: false), parentNode);
@ -37,10 +37,11 @@ namespace Xamarin.Forms.Xaml
public void Visit(ElementNode node, INode parentNode)
{
var value = Values[node];
XmlName propertyName;
if (!Values.TryGetValue(node, out var value) && Context.ExceptionHandler != null)
return;
//Set RD to VE
if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName)) {
if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[node]) && ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out XmlName propertyName)) {
if ((propertyName.LocalName == "Resources" ||
propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary) {
var source = Values[parentNode];
@ -51,7 +52,8 @@ namespace Xamarin.Forms.Xaml
//Only proceed further if the node is a keyless RD
if ( parentNode is IElementNode
&& typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)])
&& 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
@ -74,7 +76,8 @@ namespace Xamarin.Forms.Xaml
if (enode is null)
return false;
if ( parentNode is IElementNode
&& typeof(ResourceDictionary).IsAssignableFrom(Context.Types[((IElementNode)parentNode)])
&& Context.Types.TryGetValue((IElementNode)parentNode, out var parentType)
&& typeof(ResourceDictionary).IsAssignableFrom(parentType)
&& !((IElementNode)parentNode).Properties.ContainsKey(XmlName.xKey))
return true;
if ( parentNode is ListNode