Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Properly resolve interface members in x:Bind #18050

Merged
merged 1 commit into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,42 @@ public static string GetDeclarationHeaderFromNamedTypeSymbol(this INamedTypeSymb

public static IEnumerable<ISymbol> GetAllMembersWithName(this ITypeSymbol? symbol, string name)
{
do
if (symbol != null)
{
if (symbol != null)
foreach (var member in symbol.GetMembers(name))
{
foreach (var member in symbol.GetMembers(name))
yield return member;
}
}

if (symbol?.TypeKind == TypeKind.Interface)
{
foreach (var @interface in symbol.AllInterfaces)
{
foreach (var member in @interface.GetMembers(name))
{
yield return member;
}
}
}
else
{
do
{
symbol = symbol?.BaseType;

symbol = symbol?.BaseType;
if (symbol == null)
{
break;
}

if (symbol == null)
{
break;
}
foreach (var member in symbol.GetMembers(name))
{
yield return member;
}

} while (symbol.SpecialType != SpecialType.System_Object);
} while (symbol.SpecialType != SpecialType.System_Object);
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,89 @@ public MainPage()

await test.RunAsync();
}

[TestMethod]
public async Task TestInterfaceDerivesFromAnother()
{
var xamlFile = new XamlFile("MainPage.xaml", """
<Page
x:Class="TestRepro.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestRepro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">

<StackPanel>
<TextBox Text="{x:Bind MyFooInterface.Name, Mode=TwoWay}" />
</StackPanel>
</Page>
""");

var test = new Verify.Test(xamlFile)
{
TestState =
{
Sources =
{
"""
using System.ComponentModel;
using Microsoft.UI.Xaml.Controls;

namespace TestRepro
{
public sealed partial class MainPage : Page
{
public MainPage()
{
MyFooInterface = new MyBarClass("John Doe");
this.InitializeComponent();
}

private IMyFooInterface MyFooInterface { get; set; }
}

public partial class MyBarClass : INotifyPropertyChanged, IMyFooInterface
{
private string _name;

public MyBarClass(string name)
{
Name = name;
}

public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
}

public event PropertyChangedEventHandler PropertyChanged;
}

public interface IMyFooInterface : INameProvider
{
}

public interface INameProvider
{
string Name { get; set; }
}
}

"""
}
}
}.AddGeneratedSources();

await test.RunAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// <autogenerated />
namespace MyProject
{
/// <summary>
/// Contains all the static resources defined for the application
/// </summary>
public sealed partial class GlobalStaticResources
{
static bool _initialized;
private static bool _stylesRegistered;
private static bool _dictionariesRegistered;
internal static global::Uno.UI.Xaml.XamlParseContext __ParseContext_ { get; } = new global::Uno.UI.Xaml.XamlParseContext()
{
AssemblyName = "TestProject",
}
;

static GlobalStaticResources()
{
Initialize();
}
public static void Initialize()
{
if (!_initialized)
{
_initialized = true;
global::Uno.UI.GlobalStaticResources.Initialize();
global::Uno.UI.GlobalStaticResources.RegisterDefaultStyles();
global::Uno.UI.GlobalStaticResources.RegisterResourceDictionariesBySource();
}
}
public static void RegisterDefaultStyles()
{
if(!_stylesRegistered)
{
_stylesRegistered = true;
RegisterDefaultStyles_MainPage_d6cd66944958ced0c513e0a04797b51d();
}
}
// Register ResourceDictionaries using ms-appx:/// syntax, this is called for external resources
public static void RegisterResourceDictionariesBySource()
{
if(!_dictionariesRegistered)
{
_dictionariesRegistered = true;
}
}
// Register ResourceDictionaries using ms-resource:/// syntax, this is called for local resources
internal static void RegisterResourceDictionariesBySourceLocal()
{
}
static partial void RegisterDefaultStyles_MainPage_d6cd66944958ced0c513e0a04797b51d();

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// <auto-generated />
[assembly: global::System.Reflection.AssemblyMetadata("UnoHasLocalizationResources", "False")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// <autogenerated />
#pragma warning disable CS0114
#pragma warning disable CS0108
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Uno.UI;
using Uno.UI.Xaml;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.UI.Xaml.Shapes;
using Windows.UI.Text;
using Uno.Extensions;
using Uno;
using Uno.UI.Helpers;
using Uno.UI.Helpers.Xaml;
using MyProject;

#if __ANDROID__
using _View = Android.Views.View;
#elif __IOS__
using _View = UIKit.UIView;
#elif __MACOS__
using _View = AppKit.NSView;
#else
using _View = Microsoft.UI.Xaml.UIElement;
#endif

namespace TestRepro
{
partial class MainPage : global::Microsoft.UI.Xaml.Controls.Page
{
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
private const string __baseUri_prefix_MainPage_d6cd66944958ced0c513e0a04797b51d = "ms-appx:///TestProject/";
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
private const string __baseUri_MainPage_d6cd66944958ced0c513e0a04797b51d = "ms-appx:///TestProject/";
private global::Microsoft.UI.Xaml.NameScope __nameScope = new global::Microsoft.UI.Xaml.NameScope();
private void InitializeComponent()
{
NameScope.SetNameScope(this, __nameScope);
var __that = this;
base.IsParsing = true;
// Source 0\MainPage.xaml (Line 1:2)
base.Content =
new global::Microsoft.UI.Xaml.Controls.StackPanel
{
IsParsing = true,
// Source 0\MainPage.xaml (Line 10:3)
Children =
{
new global::Microsoft.UI.Xaml.Controls.TextBox
{
IsParsing = true,
// Source 0\MainPage.xaml (Line 11:4)
}
.MainPage_d6cd66944958ced0c513e0a04797b51d_XamlApply((MainPage_d6cd66944958ced0c513e0a04797b51dXamlApplyExtensions.XamlApplyHandler0)(c0 =>
{
/* _isTopLevelDictionary:False */
__that._component_0 = c0;
c0.SetBinding(
global::Microsoft.UI.Xaml.Controls.TextBox.TextProperty,
new Microsoft.UI.Xaml.Data.Binding()
{
Mode = global::Microsoft.UI.Xaml.Data.BindingMode.TwoWay,
}
.BindingApply(___b => /*defaultBindModeOneTime MyFooInterface.Name*/ global::Uno.UI.Xaml.BindingHelper.SetBindingXBindProvider(___b, __that, ___ctx => ___ctx is global::TestRepro.MainPage ___tctx ? ((true, ___tctx.MyFooInterface.Name)) : (false, default), (___ctx, __value) => { if(___ctx is global::TestRepro.MainPage ___tctx) ___tctx.MyFooInterface.Name = (string)global::Microsoft.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(string), __value); } , new [] {"MyFooInterface.Name"}))
);
global::Uno.UI.FrameworkElementHelper.SetBaseUri(c0, __baseUri_MainPage_d6cd66944958ced0c513e0a04797b51d);
c0.CreationComplete();
}
))
,
}
}
.MainPage_d6cd66944958ced0c513e0a04797b51d_XamlApply((MainPage_d6cd66944958ced0c513e0a04797b51dXamlApplyExtensions.XamlApplyHandler1)(c1 =>
{
global::Uno.UI.FrameworkElementHelper.SetBaseUri(c1, __baseUri_MainPage_d6cd66944958ced0c513e0a04797b51d);
c1.CreationComplete();
}
))
;

this
.GenericApply(((c2) =>
{
// Source 0\MainPage.xaml (Line 1:2)

// WARNING Property c2.base does not exist on {http://schemas.microsoft.com/winfx/2006/xaml/presentation}Page, the namespace is http://www.w3.org/XML/1998/namespace. This error was considered irrelevant by the XamlFileGenerator
}
))
.GenericApply(((c3) =>
{
// Class TestRepro.MainPage
global::Uno.UI.FrameworkElementHelper.SetBaseUri(c3, __baseUri_MainPage_d6cd66944958ced0c513e0a04797b51d);
c3.CreationComplete();
}
))
;
OnInitializeCompleted();

Bindings = new MainPage_Bindings(this);
Loading += (s, e) =>
{
__that.Bindings.Update();
__that.Bindings.UpdateResources();
}
;
}
partial void OnInitializeCompleted();
private global::Microsoft.UI.Xaml.Markup.ComponentHolder _component_0_Holder = new global::Microsoft.UI.Xaml.Markup.ComponentHolder(isWeak: true);
private global::Microsoft.UI.Xaml.Controls.TextBox _component_0
{
get
{
return (global::Microsoft.UI.Xaml.Controls.TextBox)_component_0_Holder.Instance;
}
set
{
_component_0_Holder.Instance = value;
}
}
private interface IMainPage_Bindings
{
void Initialize();
void Update();
void UpdateResources();
void StopTracking();
void NotifyXLoad(string name);
}
#pragma warning disable 0169 // Suppress unused field warning in case Bindings is not used.
private IMainPage_Bindings Bindings;
#pragma warning restore 0169
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
private class MainPage_Bindings : IMainPage_Bindings
{
#if UNO_HAS_UIELEMENT_IMPLICIT_PINNING
private global::System.WeakReference _ownerReference;
private global::TestRepro.MainPage Owner { get => (global::TestRepro.MainPage)_ownerReference?.Target; set => _ownerReference = new global::System.WeakReference(value); }
#else
private global::TestRepro.MainPage Owner { get; set; }
#endif
public MainPage_Bindings(global::TestRepro.MainPage owner)
{
Owner = owner;
}
void IMainPage_Bindings.NotifyXLoad(string name)
{
}
void IMainPage_Bindings.Initialize()
{
}
void IMainPage_Bindings.Update()
{
var owner = Owner;
owner._component_0.ApplyXBind();
}
void IMainPage_Bindings.UpdateResources()
{
var owner = Owner;
owner._component_0.UpdateResourceBindings(resourceContextProvider: null);
}
void IMainPage_Bindings.StopTracking()
{
}
}
}
}
namespace MyProject
{
static class MainPage_d6cd66944958ced0c513e0a04797b51dXamlApplyExtensions
{
public delegate void XamlApplyHandler0(global::Microsoft.UI.Xaml.Controls.TextBox instance);
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static global::Microsoft.UI.Xaml.Controls.TextBox MainPage_d6cd66944958ced0c513e0a04797b51d_XamlApply(this global::Microsoft.UI.Xaml.Controls.TextBox instance, XamlApplyHandler0 handler)
{
handler(instance);
return instance;
}
public delegate void XamlApplyHandler1(global::Microsoft.UI.Xaml.Controls.StackPanel instance);
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public static global::Microsoft.UI.Xaml.Controls.StackPanel MainPage_d6cd66944958ced0c513e0a04797b51d_XamlApply(this global::Microsoft.UI.Xaml.Controls.StackPanel instance, XamlApplyHandler1 handler)
{
handler(instance);
return instance;
}
}
}
Loading
Loading