Skip to content

Commit e2cf752

Browse files
authored
[XC|XSG] fix target resolution (#31229)
### Description of Change resolve type in the right xmlns for visual state targets ### Issues Fixed - fixes #31186
2 parents 2030fe1 + e7a384c commit e2cf752

File tree

6 files changed

+137
-15
lines changed

6 files changed

+137
-15
lines changed

src/Controls/src/Build.Tasks/CompiledConverters/BindablePropertyConverter.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ static bool IsOfAnyType(XmlType xmlType, params string[] types)
3737
return true;
3838
return false;
3939
}
40+
4041
public FieldReference GetBindablePropertyFieldReference(string value, ILContext context, ModuleDefinition module, BaseNode node)
4142
{
4243
FieldReference bpRef = null;
43-
string typeName = null, propertyName = null;
44+
XmlType typeName = null;
45+
string propertyName = null;
4446

4547
var parts = value.Split('.');
4648
if (parts.Length == 1)
@@ -54,7 +56,7 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
5456
}
5557
else if (IsOfAnyType(parent.XmlType, nameof(VisualState)))
5658
{
57-
typeName = FindTypeNameForVisualState(parent, node);
59+
typeName = FindTypeNameForVisualState(parent, node, context);
5860
}
5961
}
6062
else if (IsOfAnyType((node.Parent as ElementNode)?.XmlType, nameof(Trigger)))
@@ -65,7 +67,8 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
6567
}
6668
else if (parts.Length == 2)
6769
{
68-
typeName = parts[0];
70+
var targetType = parts[0];
71+
typeName = TypeArgumentsParser.ParseSingle(targetType, node.NamespaceResolver, (IXmlLineInfo)node);
6972
propertyName = parts[1];
7073
}
7174
else
@@ -74,7 +77,7 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
7477
if (typeName == null || propertyName == null)
7578
throw new BuildException(Conversion, node, null, value, typeof(BindableProperty));
7679

77-
var typeRef = XmlTypeExtensions.GetTypeReference(context.Cache, typeName, module, node);
80+
var typeRef = typeName.GetTypeReference(context.Cache, module, node);
7881
if (typeRef == null)
7982
throw new BuildException(TypeResolution, node, null, typeName);
8083

@@ -83,11 +86,14 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
8386
throw new BuildException(PropertyResolution, node, null, propertyName, typeRef.Name);
8487
return bpRef;
8588

86-
static string GetTargetTypeName(INode node)
87-
=> ((node as ElementNode).Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
89+
static XmlType GetTargetTypeName(INode node)
90+
{
91+
var targetType = ((node as ElementNode).Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
92+
return TypeArgumentsParser.ParseSingle(targetType, node.NamespaceResolver, (IXmlLineInfo)node);
93+
}
8894
}
8995

90-
static string FindTypeNameForVisualState(IElementNode parent, IXmlLineInfo lineInfo)
96+
static XmlType FindTypeNameForVisualState(IElementNode parent, IXmlLineInfo lineInfo, ILContext context)
9197
{
9298
//1. parent is VisualState, don't check that
9399

@@ -105,9 +111,12 @@ static string FindTypeNameForVisualState(IElementNode parent, IXmlLineInfo lineI
105111

106112
//4. target is now a Setter in a Style, or a VE
107113
if (IsOfAnyType(target.XmlType, nameof(Setter)))
108-
return ((target?.Parent as IElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
114+
{
115+
var targetType = ((target?.Parent as IElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
116+
return TypeArgumentsParser.ParseSingle(targetType, parent.NamespaceResolver, lineInfo);
117+
}
109118
else
110-
return target.XmlType.Name;
119+
return target.XmlType;
111120
}
112121

113122
public static FieldReference GetBindablePropertyFieldReference(XamlCache cache, TypeReference typeRef, string propertyName, ModuleDefinition module)

src/Controls/src/Build.Tasks/XamlCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ static TValue GetOrAdd<TKey, TValue>(Dictionary<TKey, TValue> dictionary, TKey k
3030
return value;
3131
}
3232

33-
public IList<XmlnsDefinitionAttribute> GetXmlsDefinitions(ModuleDefinition module, Func<ModuleDefinition, IList<XmlnsDefinitionAttribute>> valueFactory) =>
33+
public IList<XmlnsDefinitionAttribute> GetXmlnsDefinitions(ModuleDefinition module, Func<ModuleDefinition, IList<XmlnsDefinitionAttribute>> valueFactory) =>
3434
GetOrAdd(_xmlnsDefinitions, module, valueFactory);
3535

3636
public TypeDefinition Resolve(TypeReference typeReference) =>

src/Controls/src/Build.Tasks/XmlTypeExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public static TypeReference GetTypeReference(XamlCache cache, string namespaceUR
101101

102102
public static bool TryGetTypeReference(this XmlType xmlType, XamlCache cache, ModuleDefinition module, IXmlLineInfo xmlInfo, bool expandToExtension, out TypeReference typeReference)
103103
{
104-
IList<XmlnsDefinitionAttribute> xmlnsDefinitions = cache.GetXmlsDefinitions(module, GatherXmlnsDefinitionAttributes);
104+
IList<XmlnsDefinitionAttribute> xmlnsDefinitions = cache.GetXmlnsDefinitions(module, GatherXmlnsDefinitionAttributes);
105105

106106
var typeArguments = xmlType.TypeArguments;
107107

src/Controls/src/SourceGen/NodeSGExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,14 +625,17 @@ public static IFieldSymbol GetBindableProperty(this ValueNode node, SourceGenCon
625625
else
626626
target = (IElementNode)target.Parent;
627627

628-
string? typeName = null;
628+
XmlType? typeName = null;
629629
//4. target is now a Setter in a Style, or a VE
630630
if (IsOfAnyType(target.XmlType, "Setter"))
631-
typeName = ((target?.Parent as IElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
631+
{
632+
var targetType = ((target?.Parent as IElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
633+
typeName = TypeArgumentsParser.ParseSingle(targetType, parent.NamespaceResolver, lineInfo);
634+
}
632635
else
633-
typeName = target.XmlType.Name;
636+
typeName = target.XmlType;
634637

635-
return XmlTypeExtensions.GetTypeSymbol(typeName!, context.ReportDiagnostic, context.Compilation, context.XmlnsCache, parent);
638+
return typeName!.GetTypeSymbol(context.ReportDiagnostic, context.Compilation, context.XmlnsCache);
636639
}
637640

638641
public static bool RepresentsType(this INode node, string namespaceUri, string name)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4+
xmlns:local="clr-namespace:Microsoft.Maui.Controls.Xaml.UnitTests"
5+
x:Class="Microsoft.Maui.Controls.Xaml.UnitTests.Maui31186"
6+
Title="Maui31186">
7+
<local:MyButton
8+
x:Name="CounterBtn"
9+
Text="Click me"
10+
SemanticProperties.Hint="Counts the number of times you click"
11+
Clicked="OnCounterClicked"
12+
HorizontalOptions="Fill">
13+
<VisualStateManager.VisualStateGroups>
14+
<VisualStateGroup x:Name="CommonStates">
15+
<VisualState x:Name="Normal"/>
16+
<VisualState x:Name="Disabled">
17+
<VisualState.Setters>
18+
<Setter Property="BackgroundColor" Value="LightBlue"/>
19+
</VisualState.Setters>
20+
</VisualState>
21+
</VisualStateGroup>
22+
</VisualStateManager.VisualStateGroups>
23+
</local:MyButton>
24+
</ContentPage>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using Microsoft.Maui.Graphics;
3+
using NUnit.Framework;
4+
5+
using static Microsoft.Maui.Controls.Xaml.UnitTests.MockSourceGenerator;
6+
7+
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
8+
9+
public class MyButton : Button
10+
{
11+
12+
}
13+
14+
[XamlProcessing(XamlInflator.Default, true)]
15+
public partial class Maui31186 : ContentPage
16+
{
17+
public Maui31186()
18+
{
19+
InitializeComponent();
20+
}
21+
int count = 0;
22+
23+
void OnCounterClicked(object sender, EventArgs e)
24+
{
25+
count++;
26+
27+
if (count == 1)
28+
CounterBtn.Text = $"Clicked {count} time";
29+
else
30+
CounterBtn.Text = $"Clicked {count} times";
31+
}
32+
33+
[TestFixture]
34+
class Tests
35+
{
36+
[Test]
37+
public void XmlnsResolutionForVisualState([Values] XamlInflator inflator)
38+
{
39+
if (inflator == XamlInflator.SourceGen)
40+
{
41+
var result = CreateMauiCompilation()
42+
.WithAdditionalSource(
43+
"""
44+
using System;
45+
using Microsoft.Maui.Graphics;
46+
using NUnit.Framework;
47+
48+
using static Microsoft.Maui.Controls.Xaml.UnitTests.MockSourceGenerator;
49+
50+
namespace Microsoft.Maui.Controls.Xaml.UnitTests;
51+
52+
public class MyButton : Button
53+
{
54+
55+
}
56+
57+
[XamlProcessing(XamlInflator.Runtime, true)]
58+
public partial class Maui31186 : ContentPage
59+
{
60+
public Maui31186()
61+
{
62+
InitializeComponent();
63+
}
64+
int count = 0;
65+
66+
void OnCounterClicked(object sender, EventArgs e)
67+
{
68+
count++;
69+
70+
if (count == 1)
71+
CounterBtn.Text = $"Clicked {count} time";
72+
else
73+
CounterBtn.Text = $"Clicked {count} times";
74+
}
75+
}
76+
""")
77+
.RunMauiSourceGenerator(typeof(Maui31186));
78+
Assert.That(result.Diagnostics, Is.Empty);
79+
}
80+
var page = new Maui31186(inflator);
81+
Assert.That(page, Is.Not.Null);
82+
VisualStateManager.GoToState(page.CounterBtn, "Disabled");
83+
Assert.That(page.CounterBtn.BackgroundColor, Is.EqualTo(Colors.LightBlue));
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)