Skip to content
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
15 changes: 15 additions & 0 deletions src/Controls/src/SourceGen/GeneratorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,19 @@ static void SimplifyOnPlatform(XmlNode node, string? targetFramework, XmlNamespa
}
return null;
}

/// <summary>
/// Formats a value as a culture-independent C# literal for source generation.
/// Uses SymbolDisplay.FormatPrimitive to ensure proper handling of special values like NaN and Infinity
/// but also numeric types and makes sure they are formatted correctly.
/// </summary>
/// <param name="value">The value to format</param>
/// <param name="quoted">Whether to include quotes around the formatted value</param>
/// <returns>A culture-independent string representation suitable for source generation</returns>
public static string FormatInvariant(object value, bool quoted = false)
{
return SymbolDisplay.FormatPrimitive(value, quoteStrings: quoted, useHexadecimalNumbers: false);
}
Comment on lines +410 to +413

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static string FormatInvariant(object value, bool quoted = false)
{
return SymbolDisplay.FormatPrimitive(value, quoteStrings: quoted, useHexadecimalNumbers: false);
}
extension(SymbolDisplay)
{
public static string FormatPrimitive(object value, bool quotedStrings = false) => SymbolDisplay.FormatPrimitive(value, quotedStrings, false);
}



}
35 changes: 18 additions & 17 deletions src/Controls/src/SourceGen/KnownTypeConverters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Microsoft.Maui.Controls.SourceGen;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.Maui.Controls.Xaml;
using static LocationHelpers;
using static GeneratorHelpers;

static class KnownTypeConverters
{
Expand Down Expand Up @@ -221,7 +222,7 @@ public static string ConvertRect(string value, BaseNode node, ITypeSymbol toType
&& double.TryParse(xywh[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double w)
&& double.TryParse(xywh[3], NumberStyles.Number, CultureInfo.InvariantCulture, out double h))
{
return $"new global::Microsoft.Maui.Graphics.Rect({x}, {y}, {w}, {h})";
return $"new global::Microsoft.Maui.Graphics.Rect({FormatInvariant(x)}, {FormatInvariant(y)}, {FormatInvariant(w)}, {FormatInvariant(h)})";
}
}

Expand Down Expand Up @@ -273,7 +274,7 @@ public static string ConvertPoint(string value, BaseNode node, ITypeSymbol toTyp
if (xy.Length == 2 && double.TryParse(xy[0], NumberStyles.Number, CultureInfo.InvariantCulture, out var x)
&& double.TryParse(xy[1], NumberStyles.Number, CultureInfo.InvariantCulture, out var y))
{
return $"new global::Microsoft.Maui.Graphics.Point({x}, {y})";
return $"new global::Microsoft.Maui.Graphics.Point({FormatInvariant(x)}, {FormatInvariant(y)})";
}
}

Expand All @@ -298,21 +299,21 @@ public static string ConvertThickness(string value, BaseNode node, ITypeSymbol t
case 2:
if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double h)
&& double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double v))
return $"new global::Microsoft.Maui.Thickness({h}, {v})";
return $"new global::Microsoft.Maui.Thickness({FormatInvariant(h)}, {FormatInvariant(v)})";
break;
case 4:
if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double l)
&& double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double t)
&& double.TryParse(thickness[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double r)
&& double.TryParse(thickness[3], NumberStyles.Number, CultureInfo.InvariantCulture, out double b))
return $"new global::Microsoft.Maui.Thickness({l}, {t}, {r}, {b})";
return $"new global::Microsoft.Maui.Thickness({FormatInvariant(l)}, {FormatInvariant(t)}, {FormatInvariant(r)}, {FormatInvariant(b)})";
break;
}
}
else
{ //single uniform thickness
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double l))
return $"new global::Microsoft.Maui.Thickness({l})";
return $"new global::Microsoft.Maui.Thickness({FormatInvariant(l)})";
}
}

Expand All @@ -337,17 +338,17 @@ public static string ConvertCornerRadius(string value, BaseNode node, ITypeSymbo
&& double.TryParse(cornerRadius[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double tr)
&& double.TryParse(cornerRadius[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double bl)
&& double.TryParse(cornerRadius[3], NumberStyles.Number, CultureInfo.InvariantCulture, out double br))
return $"new global::Microsoft.Maui.CornerRadius({tl}, {tr}, {bl}, {br})";
return $"new global::Microsoft.Maui.CornerRadius({FormatInvariant(tl)}, {FormatInvariant(tr)}, {FormatInvariant(bl)}, {FormatInvariant(br)})";

if (cornerRadius.Length > 1
&& cornerRadius.Length < 4
&& double.TryParse(cornerRadius[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double l))
return $"new global::Microsoft.Maui.CornerRadius({l})";
return $"new global::Microsoft.Maui.CornerRadius({FormatInvariant(l)})";
}
else
{ //single uniform CornerRadius
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double l))
return $"new global::Microsoft.Maui.CornerRadius({l})";
return $"new global::Microsoft.Maui.CornerRadius({FormatInvariant(l)})";
}
}

Expand Down Expand Up @@ -413,10 +414,10 @@ public static string ConvertFlexBasis(string value, BaseNode node, ITypeSymbol t

if (value.EndsWith("%", StringComparison.OrdinalIgnoreCase)
&& float.TryParse(value.Substring(0, value.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out float relflex))
return $"new global::Microsoft.Maui.Layouts.FlexBasis({relflex / 100}, true)";
return $"new global::Microsoft.Maui.Layouts.FlexBasis({FormatInvariant(relflex / 100)}, true)";

if (float.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out float flex))
return $"new global::Microsoft.Maui.Layouts.FlexBasis({flex}, false)";
return $"new global::Microsoft.Maui.Layouts.FlexBasis({FormatInvariant(flex)}, false)";
}

context.ReportDiagnostic(Diagnostic.Create(Descriptors.FlexBasisConversionFailed, LocationCreate(context.FilePath!, xmlLineInfo, value), value));
Expand All @@ -431,7 +432,7 @@ public static string ConvertFontSize(string value, BaseNode node, ITypeSymbol to
{
value = value.Trim();
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double size))
return $"{SymbolDisplay.FormatPrimitive(size, true, false)}D";
return $"{FormatInvariant(size, quoted: true)}D";


var namedSizeSymbol = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.NamedSize")!;
Expand Down Expand Up @@ -490,7 +491,7 @@ public static string ConvertGridLength(string value, BaseNode node, ITypeSymbol
{
if (double.TryParse(value.Substring(0, value.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out double val))
{
return $"new global::Microsoft.Maui.GridLength({val}, global::Microsoft.Maui.GridUnitType.Star)";
return $"new global::Microsoft.Maui.GridLength({FormatInvariant(val)}, global::Microsoft.Maui.GridUnitType.Star)";
}
}
else if (value.Equals("Auto", StringComparison.OrdinalIgnoreCase))
Expand All @@ -499,7 +500,7 @@ public static string ConvertGridLength(string value, BaseNode node, ITypeSymbol
}
else if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double val))
{
return $"new global::Microsoft.Maui.GridLength({val}, global::Microsoft.Maui.GridUnitType.Absolute)";
return $"new global::Microsoft.Maui.GridLength({FormatInvariant(val)}, global::Microsoft.Maui.GridUnitType.Absolute)";
}
}

Expand Down Expand Up @@ -606,7 +607,7 @@ internal static string ConvertPointCollection(string value, BaseNode node, IType
}
else
{
pointCollection.Add(ConvertPoint($"{x},{number}", node, toType, context));
pointCollection.Add(ConvertPoint($"{FormatInvariant(x)},{FormatInvariant(number)}", node, toType, context));
hasX = false;
}
}
Expand Down Expand Up @@ -678,14 +679,14 @@ internal static string ConvertStrokeShape(string value, BaseNode node, ITypeSymb
if (coordinates.Length == 2 && double.TryParse(coordinates[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double x1)
&& double.TryParse(coordinates[1], NumberStyles.Number, CultureInfo.InvariantCulture, out double y1))
{
return $"new global::Microsoft.Maui.Controls.Shapes.Line {{ X1 = {x1}, Y1 = {y1} }}";
return $"new global::Microsoft.Maui.Controls.Shapes.Line {{ X1 = {FormatInvariant(x1)}, Y1 = {FormatInvariant(y1)} }}";
}
else if (coordinates.Length == 4 && double.TryParse(coordinates[0], NumberStyles.Number, CultureInfo.InvariantCulture, out x1)
&& double.TryParse(coordinates[1], NumberStyles.Number, CultureInfo.InvariantCulture, out y1)
&& double.TryParse(coordinates[2], NumberStyles.Number, CultureInfo.InvariantCulture, out double x2)
&& double.TryParse(coordinates[3], NumberStyles.Number, CultureInfo.InvariantCulture, out double y2))
{
return $"new global::Microsoft.Maui.Controls.Shapes.Line {{ X1 = {x1}, Y1 = {y1}, X2 = {x2}, Y2 = {y2} }}";
return $"new global::Microsoft.Maui.Controls.Shapes.Line {{ X1 = {FormatInvariant(x1)}, Y1 = {FormatInvariant(y1)}, X2 = {FormatInvariant(x2)}, Y2 = {FormatInvariant(y2)} }}";
}
}

Expand Down Expand Up @@ -822,7 +823,7 @@ internal static string ConvertConstraint(string value, BaseNode node, ITypeSymbo
value = value.Trim();

if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out var size))
return $"global::Microsoft.Maui.Controls.Compatibility.Constraint.Constant({size})";
return $"global::Microsoft.Maui.Controls.Compatibility.Constraint.Constant({FormatInvariant(size)})";
}

#pragma warning disable RS0030 // Do not use banned APIs
Expand Down
Loading
Loading