// IL_008e: newobj instance void class [mscorlib]System.Tuple`2<class [mscorlib]System.Func`2<class ViewModel, object>, string>::'.ctor'(!0, !1)
// IL_0093: stelem.ref
- yield return Instruction.Create(OpCodes.Ldc_I4, properties.Count);
- yield return Instruction.Create(OpCodes.Newarr, tupleRef);
+ yield return Create(Ldc_I4, properties.Count);
+ yield return Create(Newarr, tupleRef);
for (var i = 0; i < properties.Count; i++) {
- yield return Instruction.Create(OpCodes.Dup);
- yield return Instruction.Create(OpCodes.Ldc_I4, i);
- yield return Instruction.Create(OpCodes.Ldnull);
- yield return Instruction.Create(OpCodes.Ldftn, partGetters [i]);
- yield return Instruction.Create(OpCodes.Newobj, module.ImportReference(funcCtor));
- yield return Instruction.Create(OpCodes.Ldstr, properties [i].Item1.Name);
- yield return Instruction.Create(OpCodes.Newobj, module.ImportReference(tupleCtor));
- yield return Instruction.Create(OpCodes.Stelem_Ref);
+ yield return Create(Dup);
+ yield return Create(Ldc_I4, i);
+ yield return Create(Ldnull);
+ yield return Create(Ldftn, partGetters [i]);
+ yield return Create(Newobj, module.ImportReference(funcCtor));
+ yield return Create(Ldstr, properties [i].Item1.Name);
+ yield return Create(Newobj, module.ImportReference(tupleCtor));
+ yield return Create(Stelem_Ref);
}
}
//If it's a BP, SetValue ()
if (CanSetValue(bpRef, attached, valueNode, iXmlLineInfo, context))
- return SetValue(parent, bpRef, valueNode, iXmlLineInfo, context);
+ return SetValue(parent, bpRef, valueNode, iXmlLineInfo, context).Concat(RegisterSourceInfo(context, valueNode));
//If it's a property, set it
if (CanSet(parent, localName, valueNode, context))
- return Set(parent, localName, valueNode, iXmlLineInfo, context);
+ return Set(parent, localName, valueNode, iXmlLineInfo, context).Concat(RegisterSourceInfo(context, valueNode));
//If it's an already initialized property, add to it
if (CanAdd(parent, propertyName, valueNode, iXmlLineInfo, context))
- return Add(parent, propertyName, valueNode, iXmlLineInfo, context);
+ return Add(parent, propertyName, valueNode, iXmlLineInfo, context).Concat(RegisterSourceInfo(context, valueNode));
throw new XamlParseException($"No property, bindable property, or event found for '{localName}', or mismatching type between value and property.", iXmlLineInfo);
}
+ internal static IEnumerable<Instruction> RegisterSourceInfo(ILContext context, INode valueNode)
+ {
+ if (!context.DefineDebug)
+ yield break;
+ if (!(valueNode is IXmlLineInfo lineInfo))
+ yield break;
+ if (!(valueNode is IElementNode elementNode))
+ yield break;
+ if (context.Variables[elementNode].VariableType.IsValueType)
+ yield break;
+
+ var module = context.Body.Method.Module;
+
+ yield return Create(Ldloc, context.Variables[elementNode]); //target
+
+ yield return Create(Ldstr, context.XamlFilePath);
+ yield return Create(Ldc_I4, (int)UriKind.RelativeOrAbsolute);
+ yield return Create(Newobj, module.ImportCtorReference(("System", "System", "Uri"),
+ parameterTypes: new[] {
+ ("mscorlib", "System", "String"),
+ ("System", "System", "UriKind"),
+ })); //uri
+
+ yield return Create(Ldc_I4, lineInfo.LineNumber); //lineNumber
+ yield return Create(Ldc_I4, lineInfo.LinePosition); //linePosition
+
+ yield return Create(Call, module.ImportMethodReference(("Xamarin.Forms.Xaml", "Xamarin.Forms.Xaml.Diagnostics", "VisualDiagnostics"),
+ methodName: "RegisterSourceInfo",
+ parameterTypes: new[] {
+ ("mscorlib", "System", "Object"),
+ ("System", "System", "Uri"),
+ ("mscorlib", "System", "Int32"),
+ ("mscorlib", "System", "Int32")},
+ isStatic: true));
+ }
+
public static IEnumerable<Instruction> GetPropertyValue(VariableDefinition parent, XmlName propertyName, ILContext context, IXmlLineInfo lineInfo, out TypeReference propertyType)
{
var module = context.Body.Method.Module;
templateIl.Emit(OpCodes.Nop);
var templateContext = new ILContext(templateIl, loadTemplate.Body, module, parentValues)
{
- Root = root
+ Root = root,
+ DefineDebug = parentContext.DefineDebug,
+ XamlFilePath = parentContext.XamlFilePath,
};
node.Accept(new CreateObjectVisitor(templateContext), null);
node.Accept(new SetNamescopesAndRegisterNamesVisitor(templateContext), null);
LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing {0}.InitializeComponent ()");
Exception e;
- if (!TryCoreCompile(initComp, initCompRuntime, rootnode, out e)) {
+ if (!TryCoreCompile(initComp, initCompRuntime, rootnode, xamlFilePath, out e)) {
success = false;
LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed.");
(thrownExceptions = thrownExceptions ?? new List<Exception>()).Add(e);
return success;
}
- bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, out Exception exception)
+ bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, string xamlFilePath, out Exception exception)
{
try {
var body = new MethodBody(initComp);
il.Append(nop);
}
- var visitorContext = new ILContext(il, body, module);
+ var visitorContext = new ILContext(il, body, module) {
+ DefineDebug = DebugSymbols || (!string.IsNullOrEmpty(DebugType) && DebugType.ToLowerInvariant() != "none"),
+ XamlFilePath = xamlFilePath
+ };
+
rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
rootnode.Accept(new SetResourcesVisitor(visitorContext), null);
rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null);
+ il.Append(SetPropertiesVisitor.RegisterSourceInfo(visitorContext, rootnode));
+
il.Emit(Ret);
initComp.Body = body;
exception = null;
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Diagnostics;
+using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Xamarin.Forms.Xaml.Diagnostics
{
- class VisualDiagnostics
+ public class VisualDiagnostics
{
static ConditionalWeakTable<object, XamlSourceInfo> sourceInfos = new ConditionalWeakTable<object, XamlSourceInfo>();
- internal static void RegisterSourceInfo(object target, Uri uri, int lineNumber, int linePosition)
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void RegisterSourceInfo(object target, Uri uri, int lineNumber, int linePosition)
{
- if (DebuggerHelper.DebuggerIsAttached && !sourceInfos.TryGetValue(target, out _))
+ if (target != null && DebuggerHelper.DebuggerIsAttached && !sourceInfos.TryGetValue(target, out _))
sourceInfos.Add(target, new XamlSourceInfo(uri, lineNumber, linePosition));
}
+ [EditorBrowsable(EditorBrowsableState.Never)]
internal static void SendVisualTreeChanged(object parent, object child)
{
if (DebuggerHelper.DebuggerIsAttached)
public static XamlSourceInfo GetXamlSourceInfo(object obj) => sourceInfos.TryGetValue(obj, out var sourceinfo) ? sourceinfo : null;
}
- class XamlSourceInfo
+ public class XamlSourceInfo
{
public XamlSourceInfo(Uri sourceUri, int lineNumber, int linePosition)
{
}
}
- class VisualTreeChangeEventArgs : EventArgs
+ public class VisualTreeChangeEventArgs : EventArgs
{
public VisualTreeChangeEventArgs(object parent, object child, int childIndex, VisualTreeChangeType changeType)
{
public VisualTreeChangeType ChangeType { get; }
}
- enum VisualTreeChangeType
+ public enum VisualTreeChangeType
{
Add = 0,
Remove = 1