[XamlC] throw XPE on missing resource key (#7073)

When a resource was missing a key (non-implicit resource), XamlC was throwing
an AssemblyResolutionException instead of a proper XamlParseException when the
type of the resource was in a different xmlns than the default Forms one.

All the other cases are fine (default xmlns, or non-compiled Xaml)

- fixes AB#946693
This commit is contained in:
Stephane Delcroix 2019-08-08 10:46:17 +02:00 коммит произвёл GitHub
Родитель ec218f165a
Коммит 2cbd1f008b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 68 добавлений и 2 удалений

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

@ -192,6 +192,28 @@ namespace Xamarin.Forms.Build.Tasks
return module.ImportReference(methodRef.ResolveGenericParameters(type.MakeGenericInstanceType(classArguments), module));
}
public static MethodReference ImportMethodReference(this ModuleDefinition module,
TypeReference type,
string methodName,
TypeReference[] parameterTypes = null,
TypeReference[] classArguments = null,
bool isStatic = false)
{
return module.ImportMethodReference(type,
methodName: methodName,
predicate: md => {
if (md.IsStatic != isStatic)
return false;
if (md.Parameters.Count != (parameterTypes?.Length ?? 0))
return false;
for (var i = 0; i < md.Parameters.Count; i++)
if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, parameterTypes[i]))
return false;
return true;
},
classArguments: classArguments);
}
public static MethodReference ImportMethodReference(this ModuleDefinition module,
(string assemblyName, string clrNamespace, string typeName) type,
string methodName,

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

@ -1334,9 +1334,9 @@ namespace Xamarin.Forms.Build.Tasks
//is there a RD.Add() overrides that accepts this ?
var nodeTypeRef = context.Variables[node].VariableType;
var module = context.Body.Method.Module;
if (module.ImportMethodReference(("Xamarin.Forms.Core", "Xamarin.Forms", "ResourceDictionary"),
if (module.ImportMethodReference(module.GetTypeDefinition(("Xamarin.Forms.Core", "Xamarin.Forms", "ResourceDictionary")),
methodName: "Add",
parameterTypes: new[] { (nodeTypeRef.Scope.Name, nodeTypeRef.Namespace, nodeTypeRef.Name) }) != null)
parameterTypes: new[] { (nodeTypeRef) }) != null)
return true;
throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", lineInfo);

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

@ -0,0 +1,10 @@
<?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.AB946693"
xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests">
<ContentPage.Resources>
<local:Gh6192Template/>
</ContentPage.Resources>
</ContentPage>

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

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Xamarin.Forms;
using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
[XamlCompilation(XamlCompilationOptions.Skip)]
public partial class AB946693 : ContentPage
{
public AB946693() => InitializeComponent();
public AB946693(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 KeylessResourceThrowsMeaningfulException([Values(false, true)]bool useCompiledXaml)
{
if (useCompiledXaml)
Assert.Throws<XamlParseException>(() => MockCompiler.Compile(typeof(AB946693)));
else
Assert.Throws<XamlParseException>(() => new AB946693(useCompiledXaml));
}
}
}
}