report file location on error (#6024)
authorStephane Delcroix <stephane@delcroix.org>
Fri, 3 May 2019 18:29:08 +0000 (20:29 +0200)
committerGitHub <noreply@github.com>
Fri, 3 May 2019 18:29:08 +0000 (20:29 +0200)
Xamarin.Forms.Core/Internals/ResourceLoader.cs
Xamarin.Forms.Core/NameScopeExtensions.cs
Xamarin.Forms.Xaml.UnitTests/DesignTimeLoaderTests.cs
Xamarin.Forms.Xaml.UnitTests/XStaticException.xaml.cs
Xamarin.Forms.Xaml/XamlFilePathAttribute.cs
Xamarin.Forms.Xaml/XamlLoader.cs

index a79e8d2..28ef9e7 100644 (file)
@@ -54,6 +54,17 @@ namespace Xamarin.Forms.Internals
                        public bool UseDesignProperties { get; set; }
                }
 
-               internal static Action<Exception> ExceptionHandler { get; set; }
+               static Action<Exception> exceptionHandler1;
+
+               [Obsolete("2 is better than 1")]
+               internal static Action<Exception> ExceptionHandler {
+                       get => exceptionHandler1;
+                       set {
+                               exceptionHandler1 = value;
+                               ExceptionHandler2 = value != null ? ((Exception exception, string filepath) err) => exceptionHandler1(err.exception) : (Action<(Exception, string)>)null;
+                       }
+               }
+
+               internal static Action<(Exception exception, string filepath)> ExceptionHandler2 { get; set; }
        }
-}
\ No newline at end of file
+}
index 709305b..16eecb7 100644 (file)
@@ -10,8 +10,8 @@ namespace Xamarin.Forms
                        try {
                                return (T)element.FindByName(name);
                        }
-                       catch (InvalidCastException ice) when (ResourceLoader.ExceptionHandler != null) {
-                               ResourceLoader.ExceptionHandler(ice);
+                       catch (InvalidCastException ice) when (ResourceLoader.ExceptionHandler2 != null) {
+                               ResourceLoader.ExceptionHandler2((ice, null));
                                return default(T);
                        }
                }
index deab3d5..075e3e7 100644 (file)
@@ -23,8 +23,8 @@ namespace Xamarin.Forms.Xaml.UnitTests
                        XamlLoader.FallbackTypeResolver = null;
                        XamlLoader.ValueCreatedCallback = null;
                        XamlLoader.InstantiationFailedCallback = null;
-                       Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null;
 #pragma warning disable 0618
+                       Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null;
                        Xamarin.Forms.Xaml.Internals.XamlLoader.DoNotThrowOnExceptions = false;
 #pragma warning restore 0618
                }
@@ -365,7 +365,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                </ContentPage>";
 
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
 
                        var page = (ContentPage)XamlLoader.Create(xaml, true);
                        Assert.That(page.Content, Is.TypeOf<Button>());
@@ -533,7 +535,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                        </ContentPage>";
 
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
                        Assert.That(exceptions.Count, Is.EqualTo(2));
                }
@@ -549,7 +553,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                        </ContentPage>";
 
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
                        Assert.That(exceptions.Count, Is.EqualTo(1));
                }
@@ -568,7 +574,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                                                </StackLayout>
                                                </ContentPage>";
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
                        Assert.That(exceptions.Count, Is.GreaterThan(1));
                }
@@ -641,7 +649,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                                </StackLayout>
                                        </ContentPage>";
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
                        Assert.That(exceptions.Count, Is.GreaterThan(1));
                }
@@ -656,7 +666,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                                </ContentPage>";
 
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        var content = (ContentPage)XamlLoader.Create(xaml, true);
                        Assert.DoesNotThrow(() => content.FindByName<Button>("MyName"));
                        Assert.That(exceptions.Count, Is.GreaterThanOrEqualTo(1));
@@ -677,7 +689,9 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                                </ContentPage>";
                        XamlLoader.Create(xaml, true);
                        var exceptions = new List<Exception>();
+#pragma warning disable CS0618 // Type or member is obsolete
                        Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = exceptions.Add;
+#pragma warning restore CS0618 // Type or member is obsolete
                        Assert.DoesNotThrow(() => XamlLoader.Create(xaml, true));
                        Assert.That(exceptions.Count, Is.GreaterThanOrEqualTo(1));
                }
index fed73ab..4687071 100644 (file)
@@ -35,8 +35,8 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                Device.PlatformServices = new MockPlatformServices();
 
                                //there's a test not resetting the values correctly, but can't find which one...
-                               Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null;
 #pragma warning disable 0618
+                               Xamarin.Forms.Internals.ResourceLoader.ExceptionHandler = null;
                                Xamarin.Forms.Xaml.Internals.XamlLoader.DoNotThrowOnExceptions = false;
 #pragma warning restore 0618
                        }
index 7a6d665..7f5310e 100644 (file)
@@ -1,4 +1,6 @@
 using System;
+using System.Linq;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 
 namespace Xamarin.Forms.Xaml
@@ -6,8 +8,10 @@ namespace Xamarin.Forms.Xaml
        [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
        public sealed class XamlFilePathAttribute : Attribute
        {
-               public XamlFilePathAttribute([CallerFilePath] string filePath = "")
-               {
-               }
+               public XamlFilePathAttribute([CallerFilePath] string filePath = "") => FilePath = filePath;
+
+               public string FilePath { get; }
+
+               internal static string GetFilePathForObject(object view) => (view?.GetType().GetTypeInfo().GetCustomAttributes(typeof(XamlFilePathAttribute), false).FirstOrDefault() as XamlFilePathAttribute)?.FilePath;
        }
 }
\ No newline at end of file
index 4d69764..5ff97de 100644 (file)
@@ -88,11 +88,14 @@ namespace Xamarin.Forms.Xaml
 
                                        var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), view, (IXmlNamespaceResolver)reader);
                                        XamlParser.ParseXaml(rootnode, reader);
-                                       Visit(rootnode, new HydrationContext {
-                                               RootElement = view,
 #pragma warning disable 0618
-                                               ExceptionHandler = ResourceLoader.ExceptionHandler ?? (Internals.XamlLoader.DoNotThrowOnExceptions ? e => { } : (Action<Exception>)null)
+                                       var doNotThrow = ResourceLoader.ExceptionHandler2 != null || Internals.XamlLoader.DoNotThrowOnExceptions;
 #pragma warning restore 0618
+                                       void ehandler(Exception e) => ResourceLoader.ExceptionHandler2?.Invoke((e, XamlFilePathAttribute.GetFilePathForObject(view)));
+                                       Visit(rootnode, new HydrationContext {
+                                               RootElement = view,
+
+                                               ExceptionHandler = doNotThrow ? ehandler : (Action<Exception>)null
                                        }, useDesignProperties);
                                        break;
                                }
@@ -103,8 +106,9 @@ namespace Xamarin.Forms.Xaml
 
                public static object Create(string xaml, bool doNotThrow, bool useDesignProperties)
                {
-                       doNotThrow = doNotThrow || ResourceLoader.ExceptionHandler != null;
-                       var exceptionHandler = doNotThrow ? (ResourceLoader.ExceptionHandler ?? (e => { })) : null;
+                       doNotThrow = doNotThrow || ResourceLoader.ExceptionHandler2 != null;
+                       void ehandler(Exception e) => ResourceLoader.ExceptionHandler2?.Invoke((e, null));
+
                        object inflatedView = null;
                        using (var textreader = new StringReader(xaml))
                        using (var reader = XmlReader.Create(textreader)) {
@@ -123,7 +127,7 @@ namespace Xamarin.Forms.Xaml
                                        var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, typeArguments), null, (IXmlNamespaceResolver)reader);
                                        XamlParser.ParseXaml(rootnode, reader);
                                        var visitorContext = new HydrationContext {
-                                               ExceptionHandler = exceptionHandler,
+                                               ExceptionHandler = doNotThrow ? ehandler : (Action<Exception>)null,
                                        };
                                        var cvv = new CreateValuesVisitor(visitorContext);
                                        cvv.Visit((ElementNode)rootnode, null);