From 023d87d1ee8c0eac53ff41f313487cd3ef742f05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Sun, 19 Nov 2023 12:43:12 +0100 Subject: [PATCH 1/3] runtime warnings: include markup line number of nearest ancestor Useful when warnings are produced on control created from a CompositeControl. We still only show details of the nested control, but at least the line number now identifies where it comes from. --- .../Controls/DotvvmBindableObjectHelper.cs | 60 +++++++++++++------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs index 22f15eae24..f9d10842f0 100644 --- a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs +++ b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs @@ -485,6 +485,26 @@ static string ValueDebugString(object? value) return toStringed; } + private static (string? prefix, string tagName) FormatControlName(DotvvmBindableObject control, DotvvmConfiguration? config = null) + { + var type = control.GetType(); + if (type == typeof(HtmlGenericControl)) + return (null, ((HtmlGenericControl)control).TagName!); + var reg = config?.Markup.Controls.FirstOrDefault(c => c.Namespace == type.Namespace && Type.GetType(c.Namespace + "." + type.Name + ", " + c.Assembly) == type) ?? + config?.Markup.Controls.FirstOrDefault(c => c.Namespace == type.Namespace) ?? + config?.Markup.Controls.FirstOrDefault(c => c.Assembly == type.Assembly.GetName().Name); + var ns = reg?.TagPrefix ?? type.Namespace switch { + "DotVVM.Framework.Controls" => "dot", + "DotVVM.AutoUI.Controls" => "auto", + "DotVVM.BusinessPack.Controls" or "DotVVM.BusinessPack.PostBackHandlers" => "bp", + "DotVVM.BusinessPack.Controls.FilterOperators" => "op", + "DotVVM.BusinessPack.Controls.FilterBuilderFields" => "fp", + _ => "_" + }; + var optionsAttribute = type.GetCustomAttribute(); + return (ns, optionsAttribute?.PrimaryName ?? type.Name); + } + /// Returns somewhat readable string representing this dotvvm control. public static string DebugString(this DotvvmBindableObject control, DotvvmConfiguration? config = null, bool multiline = true, bool useHtml = false) { @@ -506,25 +526,30 @@ public static string DebugString(this DotvvmBindableObject control, DotvvmConfig select new { p, className, propName = name.propName, memberName = name.memberName, croppedValue, value, isAttached } ).ToArray(); - var location = (file: control.TryGetValue(Internal.MarkupFileNameProperty) as string, line: control.TryGetValue(Internal.MarkupLineNumberProperty) as int? ?? -1); - var reg = config?.Markup.Controls.FirstOrDefault(c => c.Namespace == type.Namespace && Type.GetType(c.Namespace + "." + type.Name + ", " + c.Assembly) == type) ?? - config?.Markup.Controls.FirstOrDefault(c => c.Namespace == type.Namespace) ?? - config?.Markup.Controls.FirstOrDefault(c => c.Assembly == type.Assembly.GetName().Name); - var ns = reg?.TagPrefix ?? type.Namespace switch { - "DotVVM.Framework.Controls" => "dot", - "DotVVM.BusinessPack.Controls" or "DotVVM.BusinessPack.PostBackHandlers" => "bp", - "DotVVM.BusinessPack.Controls.FilterOperators" => "op", - "DotVVM.BusinessPack.Controls.FilterBuilderFields" => "fp", - _ => "_" - }; - + var location = ( + file: control.TryGetValue(Internal.MarkupFileNameProperty) as string, + line: control.TryGetValue(Internal.MarkupLineNumberProperty) as int? ?? -1, + nearestControlInMarkup: (string?)null + ); + if (location.line < 0 && location.file is {}) + { + // line is not normally inherited, but we can find it manually in an ancestor control + var ancestor = control.GetAllAncestors().FirstOrDefault(c => c.TryGetValue(Internal.MarkupLineNumberProperty) is int line && line >= 0); + if (ancestor is {} && location.file.Equals(ancestor.TryGetValue(Internal.MarkupFileNameProperty))) + { + location.line = (int)ancestor.TryGetValue(Internal.MarkupLineNumberProperty)!; + var ancestorName = FormatControlName(ancestor); + location.nearestControlInMarkup = ancestorName.prefix is null ? ancestorName.tagName : $"{ancestorName.prefix}:{ancestorName.tagName}"; + } + } + var cname = FormatControlName(control, config); string dothtmlString; if (useHtml) { - var tagName = type == typeof(HtmlGenericControl) ? - $"{((HtmlGenericControl)control).TagName}" : - $"{WebUtility.HtmlEncode(ns)}:{WebUtility.HtmlEncode(type.Name)}"; + var tagName = cname.prefix is null ? + $"{cname.tagName}" : + $"{WebUtility.HtmlEncode(cname.prefix)}:{WebUtility.HtmlEncode(cname.tagName)}"; dothtmlString = $"<{tagName} "; var prefixLength = dothtmlString.Length; @@ -547,7 +572,7 @@ public static string DebugString(this DotvvmBindableObject control, DotvvmConfig } else { - var tagName = type == typeof(HtmlGenericControl) ? ((HtmlGenericControl)control).TagName : ns + ":" + type.Name; + var tagName = cname.prefix is null ? cname.tagName : cname.prefix + ":" + cname.tagName; dothtmlString = $"<{tagName} "; var prefixLength = dothtmlString.Length; @@ -567,7 +592,8 @@ public static string DebugString(this DotvvmBindableObject control, DotvvmConfig } var fileLocation = (location.file) - + (location.line >= 0 ? ":" + location.line : ""); + + (location.line >= 0 ? ":" + location.line : "") + + (location.nearestControlInMarkup is null && multiline ? "" : $" (nearest dothtml control is <{location.nearestControlInMarkup}>)"); if (useHtml) { From a6ec8a651a0e8e0764d7a929b4734f407f8b1c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Herceg?= Date: Fri, 1 Dec 2023 14:22:33 +0100 Subject: [PATCH 2/3] Added missing HTML encode --- src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs index f9d10842f0..4567fbd88d 100644 --- a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs +++ b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs @@ -548,7 +548,7 @@ public static string DebugString(this DotvvmBindableObject control, DotvvmConfig if (useHtml) { var tagName = cname.prefix is null ? - $"{cname.tagName}" : + $"{WebUtility.HtmlEncode(cname.tagName)}" : $"{WebUtility.HtmlEncode(cname.prefix)}:{WebUtility.HtmlEncode(cname.tagName)}"; dothtmlString = $"<{tagName} "; var prefixLength = dothtmlString.Length; From 841c94393baaa090829b5640f0d6964e01544b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Fri, 1 Dec 2023 14:46:17 +0100 Subject: [PATCH 3/3] Fix runtime warning nearest control info in multiline --- src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs index 4567fbd88d..80ebd5fada 100644 --- a/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs +++ b/src/Framework/Framework/Controls/DotvvmBindableObjectHelper.cs @@ -593,7 +593,7 @@ public static string DebugString(this DotvvmBindableObject control, DotvvmConfig var fileLocation = (location.file) + (location.line >= 0 ? ":" + location.line : "") - + (location.nearestControlInMarkup is null && multiline ? "" : $" (nearest dothtml control is <{location.nearestControlInMarkup}>)"); + + (location.nearestControlInMarkup is null || !multiline ? "" : $" (nearest dothtml control is <{location.nearestControlInMarkup}>)"); if (useHtml) {