Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit 132d7b7

Browse files
[X] Wrap FormatException with lineInfo (#11731)
- fixes #11711
1 parent ed86ce6 commit 132d7b7

File tree

4 files changed

+70
-16
lines changed

4 files changed

+70
-16
lines changed

Xamarin.Forms.Build.Tasks/NodeILExtensions.cs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,14 @@ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, I
131131
unboxValueTypes);
132132
}
133133

134+
static T TryFormat<T>(Func<string, T> func, IXmlLineInfo lineInfo, string str)
135+
{
136+
try {
137+
return func(str);
138+
} catch (FormatException fex) {
139+
throw new BuildException(BuildExceptionCode.Conversion, lineInfo, fex, str, typeof(T));
140+
}
141+
}
134142
public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, ILContext context,
135143
TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable<Instruction> pushServiceProvider,
136144
bool boxValueTypes, bool unboxValueTypes)
@@ -208,39 +216,39 @@ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, I
208216
if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum")
209217
yield return PushParsedEnum(targetTypeRef, str, node);
210218
else if (targetTypeRef.FullName == "System.Char")
211-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)Char.Parse(str)));
219+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(Char.Parse, node, str)));
212220
else if (targetTypeRef.FullName == "System.SByte")
213-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)SByte.Parse(str, CultureInfo.InvariantCulture)));
221+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(s => SByte.Parse(s,CultureInfo.InvariantCulture), node, str)));
214222
else if (targetTypeRef.FullName == "System.Int16")
215-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)Int16.Parse(str, CultureInfo.InvariantCulture)));
223+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(s => Int16.Parse(s, CultureInfo.InvariantCulture), node, str)));
216224
else if (targetTypeRef.FullName == "System.Int32")
217-
yield return Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture));
225+
yield return Instruction.Create(OpCodes.Ldc_I4, TryFormat(s => Int32.Parse(s, CultureInfo.InvariantCulture), node, str));
218226
else if (targetTypeRef.FullName == "System.Int64")
219-
yield return Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture));
227+
yield return Instruction.Create(OpCodes.Ldc_I8, TryFormat(s => Int64.Parse(s, CultureInfo.InvariantCulture), node, str));
220228
else if (targetTypeRef.FullName == "System.Byte")
221-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)Byte.Parse(str, CultureInfo.InvariantCulture)));
229+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(s => Byte.Parse(s, CultureInfo.InvariantCulture), node, str)));
222230
else if (targetTypeRef.FullName == "System.UInt16")
223-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)UInt16.Parse(str, CultureInfo.InvariantCulture)));
231+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(s => UInt16.Parse(s, CultureInfo.InvariantCulture), node, str)));
224232
else if (targetTypeRef.FullName == "System.UInt32")
225-
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)UInt32.Parse(str, CultureInfo.InvariantCulture)));
233+
yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(s => UInt32.Parse(s, CultureInfo.InvariantCulture), node, str)));
226234
else if (targetTypeRef.FullName == "System.UInt64")
227-
yield return Instruction.Create(OpCodes.Ldc_I8, unchecked((long)UInt64.Parse(str, CultureInfo.InvariantCulture)));
235+
yield return Instruction.Create(OpCodes.Ldc_I8, unchecked((long)TryFormat(s => UInt64.Parse(s, CultureInfo.InvariantCulture), node, str)));
228236
else if (targetTypeRef.FullName == "System.Single")
229-
yield return Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture));
237+
yield return Instruction.Create(OpCodes.Ldc_R4, TryFormat(s => Single.Parse(str, CultureInfo.InvariantCulture), node, str));
230238
else if (targetTypeRef.FullName == "System.Double")
231-
yield return Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture));
239+
yield return Instruction.Create(OpCodes.Ldc_R8, TryFormat(s => Double.Parse(str, CultureInfo.InvariantCulture), node, str));
232240
else if (targetTypeRef.FullName == "System.Boolean") {
233-
if (Boolean.Parse(str))
241+
if (TryFormat(Boolean.Parse, node, str))
234242
yield return Instruction.Create(OpCodes.Ldc_I4_1);
235243
else
236244
yield return Instruction.Create(OpCodes.Ldc_I4_0);
237245
} else if (targetTypeRef.FullName == "System.TimeSpan") {
238-
var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture);
246+
var ts = TryFormat(s => TimeSpan.Parse(s, CultureInfo.InvariantCulture), node, str);
239247
var ticks = ts.Ticks;
240248
yield return Instruction.Create(OpCodes.Ldc_I8, ticks);
241249
yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") }));
242250
} else if (targetTypeRef.FullName == "System.DateTime") {
243-
var dt = DateTime.Parse(str, CultureInfo.InvariantCulture);
251+
var dt = TryFormat(s => DateTime.Parse(s, CultureInfo.InvariantCulture), node, str);
244252
var ticks = dt.Ticks;
245253
yield return Instruction.Create(OpCodes.Ldc_I8, ticks);
246254
yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("mscorlib", "System", "DateTime"), parameterTypes: new[] { ("mscorlib", "System", "Int64") }));

Xamarin.Forms.Core/Xaml/ValueConverterProvider.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ class ValueConverterProvider : IValueConverterProvider
1212
public object Convert(object value, Type toType, Func<MemberInfo> minfoRetriever, IServiceProvider serviceProvider)
1313
{
1414
var ret = value.ConvertTo(toType, minfoRetriever, serviceProvider, out Exception exception);
15-
if (exception != null)
16-
throw exception;
15+
if (exception != null) {
16+
var lineInfo = (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider lineInfoProvider) ? lineInfoProvider.XmlLineInfo : new XmlLineInfo();
17+
throw new XamlParseException(exception.Message, serviceProvider, exception);
18+
}
1719
return ret;
1820
}
1921
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xamarin.Forms.Xaml.UnitTests.Gh11711">
3+
<ContentPage.Resources>
4+
<Style TargetType="Frame">
5+
<Setter Property="HasShadow" Value="#False"/>
6+
</Style>
7+
</ContentPage.Resources>
8+
<Frame x:Name="frame" />
9+
</ContentPage>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using NUnit.Framework;
4+
using Xamarin.Forms;
5+
using Xamarin.Forms.Build.Tasks;
6+
using Xamarin.Forms.Core.UnitTests;
7+
8+
namespace Xamarin.Forms.Xaml.UnitTests
9+
{
10+
[XamlCompilation(XamlCompilationOptions.Skip)]
11+
public partial class Gh11711 : ContentPage
12+
{
13+
public Gh11711() => InitializeComponent();
14+
public Gh11711(bool useCompiledXaml)
15+
{
16+
//this stub will be replaced at compile time
17+
}
18+
19+
[TestFixture]
20+
class Tests
21+
{
22+
[SetUp] public void Setup() => Device.PlatformServices = new MockPlatformServices();
23+
[TearDown] public void TearDown() => Device.PlatformServices = null;
24+
25+
[Test]
26+
public void FormatExceptionAreCaught([Values(false, true)] bool useCompiledXaml)
27+
{
28+
if (useCompiledXaml)
29+
Assert.Throws<BuildException>(() => MockCompiler.Compile(typeof(Gh11711)));
30+
else
31+
Assert.Throws<XamlParseException>(() => new Gh11711(useCompiledXaml));
32+
}
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)