Skip to content

Commit

Permalink
[XamlC] fix generic array
Browse files Browse the repository at this point in the history
fix generic resolution for interfaces with generic array types.

- fix #10583
  • Loading branch information
StephaneDelcroix committed Sep 11, 2023
1 parent f04c5af commit 0e4cf32
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 4 deletions.
5 changes: 3 additions & 2 deletions src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs
Expand Up @@ -414,8 +414,9 @@ public static GenericInstanceType ResolveGenericParameters(this GenericInstanceT
List<TypeReference> args = new List<TypeReference>();
for (var i = 0; i < self.GenericArguments.Count; i++)
{
var genericParameter = self.GenericArguments[i] as GenericParameter;
if (genericParameter == null)
if (self.GenericArguments[i] is ArrayType arrayType && arrayType.ElementType is GenericParameter arrayGenericParameter)
args.Add(declaringTypeReference.GenericArguments[arrayGenericParameter.Position].MakeArrayType());
else if (self.GenericArguments[i] is not GenericParameter genericParameter)
args.Add(self.GenericArguments[i].ResolveGenericParameters(declaringTypeReference));
else if (genericParameter.Type == GenericParameterType.Type)
args.Add(declaringTypeReference.GenericArguments[genericParameter.Position]);
Expand Down
9 changes: 9 additions & 0 deletions src/Controls/tests/Xaml.UnitTests/Issues/Maui10583.xaml
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://schemas.microsoft.com/dotnet/2021/maui/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Microsoft.Maui.Controls.Xaml.UnitTests"
x:Class="Microsoft.Maui.Controls.Xaml.UnitTests.Maui10583">
<ListView x:Name="lv" ItemsSource="{local:Maui10583EnumValues x:TypeArguments=local:Maui10583Enum}" />
</ContentPage>
75 changes: 75 additions & 0 deletions src/Controls/tests/Xaml.UnitTests/Issues/Maui10583.xaml.cs
@@ -0,0 +1,75 @@
using System;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Controls.Core.UnitTests;
using Microsoft.Maui.Devices;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.UnitTests;
using Microsoft.Maui.Dispatching;
using NUnit.Framework;
using System.Collections.Generic;

namespace Microsoft.Maui.Controls.Xaml.UnitTests
{
[AcceptEmptyServiceProvider]
public class Maui10583EnumValuesExtension<T> : IMarkupExtension<T[]> where T : struct, Enum
{
public T[] ProvideValue(IServiceProvider serviceProvider)
{
return Enum.GetValues<T>();
}

object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return ProvideValue(serviceProvider);
}
}

public enum Maui10583Enum {
John, Paul, George, Ringo
}

public partial class Maui10583 : ContentPage
{
public Maui10583() => InitializeComponent();
public Maui10583(bool useCompiledXaml)
{
//this stub will be replaced at compile time
}

[TestFixture]
class Tests
{
[SetUp]
public void Setup()
{
AppInfo.SetCurrent(new MockAppInfo());
DispatcherProvider.SetCurrent(new DispatcherProviderStub());

}

[TearDown]
public void TearDown()
{
DispatcherProvider.SetCurrent(null);
AppInfo.SetCurrent(null);
}

[Test]
public void GenericMarkupExtensions([Values(false, true)] bool useCompiledXaml)
{
if (true)
{
MockCompiler.Compile(typeof(Maui10583), out var methodDefinition);

}
var page = new Maui10583(useCompiledXaml);

Assert.That(page.lv.ItemsSource, Is.Not.Null);
var items = page.lv.ItemsSource as Maui10583Enum[];
Assert.That(items[1], Is.EqualTo(Maui10583Enum.Paul));


}
}
}
}
1 change: 0 additions & 1 deletion src/Controls/tests/Xaml.UnitTests/MockCompiler.cs
Expand Up @@ -11,7 +11,6 @@ public static class MockCompiler
{
public static void Compile(Type type, string targetFramework = null)
{
MethodDefinition _;
Compile(type, out _, targetFramework);
}

Expand Down
Expand Up @@ -71,6 +71,10 @@ class Grault<T> : IGrault<T>
{
}


class Zoo<T> : IGrault<T[]>
{ }

interface ICovariant<out T>
{
}
Expand Down Expand Up @@ -242,12 +246,28 @@ public void TestImplementsGenericInterface()
IList<TypeReference> arguments;
var garply = module.ImportReference(typeof(Garply<System.Byte>));

Assert.That(garply.ImplementsGenericInterface(new XamlCache(), "Microsoft.Maui.Controls.XamlcUnitTests.TypeReferenceExtensionsTests/IGrault`1<T>", out igrault, out arguments));
Assert.That(garply.ImplementsGenericInterface(new XamlCache(), "Microsoft.Maui.Controls.XamlcUnitTests.TypeReferenceExtensionsTests/IGrault`1", out igrault, out arguments));

Assert.AreEqual("System", igrault.GenericArguments[0].Namespace);
Assert.AreEqual("Byte", igrault.GenericArguments[0].Name);
Assert.AreEqual("System", arguments[0].Namespace);
Assert.AreEqual("Byte", arguments[0].Name);
}

[Test]
//https://github.com/dotnet/maui/issues/10583
public void TestImplementsGenericInterfaceWithArray()
{
GenericInstanceType igrault;
IList<TypeReference> arguments;
var garply = module.ImportReference(typeof(Zoo<System.Byte>));

Assert.That(garply.ImplementsGenericInterface(new XamlCache(), "Microsoft.Maui.Controls.XamlcUnitTests.TypeReferenceExtensionsTests/IGrault`1", out igrault, out arguments));

Assert.AreEqual("System", igrault.GenericArguments[0].Namespace);
Assert.AreEqual("Byte[]", igrault.GenericArguments[0].Name);
Assert.AreEqual("System", arguments[0].Namespace);
Assert.AreEqual("Byte[]", arguments[0].Name);
}
}
}

0 comments on commit 0e4cf32

Please sign in to comment.