[X] RegisterSourceInfo for XamlC (#8579)

When compiling in DEBUG, Register sourceInfo even for compiled code
This commit is contained in:
Stephane Delcroix 2019-11-26 01:29:40 +01:00 коммит произвёл Samantha Houts
Родитель 5bee239756
Коммит 7573226b58
8 изменённых файлов: 77 добавлений и 29 удалений

Просмотреть файл

@ -506,7 +506,7 @@ namespace Xamarin.Forms.Build.Tasks
}
break;
case "System.Uri":
if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out Uri outuri)) {
if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out _)) {
var vardef = new VariableDefinition(module.ImportReference(("System", "System", "Uri")));
Context.Body.Variables.Add(vardef);
//Use an extra temp var so we can push the value to the stack, just like other cases

Просмотреть файл

@ -39,5 +39,7 @@ namespace Xamarin.Forms.Build.Tasks
public MethodBody Body { get; private set; }
public ModuleDefinition Module { get; private set; }
public bool DefineDebug { get; internal set; }
public string XamlFilePath { get; internal set; }
}
}

Просмотреть файл

@ -6,7 +6,7 @@ namespace Xamarin.Forms.Build.Tasks
{
class ILRootNode : RootNode
{
public ILRootNode(XmlType xmlType, TypeReference typeReference, IXmlNamespaceResolver nsResolver) : base(xmlType, nsResolver)
public ILRootNode(XmlType xmlType, TypeReference typeReference, IXmlNamespaceResolver nsResolver, int linenumber = -1, int lineposition = -1) : base(xmlType, nsResolver, linenumber: linenumber, lineposition: lineposition)
{
TypeReference = typeReference;
}

Просмотреть файл

@ -858,18 +858,18 @@ namespace Xamarin.Forms.Build.Tasks
// 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);
}
}
@ -892,19 +892,55 @@ namespace Xamarin.Forms.Build.Tasks
//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;
@ -1492,7 +1528,9 @@ namespace Xamarin.Forms.Build.Tasks
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);

Просмотреть файл

@ -189,7 +189,7 @@ namespace Xamarin.Forms.Build.Tasks
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);
@ -263,7 +263,7 @@ namespace Xamarin.Forms.Build.Tasks
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);
@ -328,7 +328,11 @@ namespace Xamarin.Forms.Build.Tasks
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);
@ -339,6 +343,8 @@ namespace Xamarin.Forms.Build.Tasks
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;

Просмотреть файл

@ -62,7 +62,7 @@ namespace Xamarin.Forms.Build.Tasks
}
XamlParser.ParseXaml(
rootnode = new ILRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), typeReference, reader as IXmlNamespaceResolver), reader);
rootnode = new ILRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), typeReference, reader as IXmlNamespaceResolver, ((IXmlLineInfo)reader).LineNumber, ((IXmlLineInfo)reader).LinePosition), reader);
break;
}
}

Просмотреть файл

@ -1,21 +1,23 @@
// 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)
@ -26,7 +28,7 @@ namespace Xamarin.Forms.Xaml.Diagnostics
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)
{
@ -47,7 +49,7 @@ namespace Xamarin.Forms.Xaml.Diagnostics
}
}
class VisualTreeChangeEventArgs : EventArgs
public class VisualTreeChangeEventArgs : EventArgs
{
public VisualTreeChangeEventArgs(object parent, object child, int childIndex, VisualTreeChangeType changeType)
{
@ -63,7 +65,7 @@ namespace Xamarin.Forms.Xaml.Diagnostics
public VisualTreeChangeType ChangeType { get; }
}
enum VisualTreeChangeType
public enum VisualTreeChangeType
{
Add = 0,
Remove = 1

Просмотреть файл

@ -190,7 +190,7 @@ namespace Xamarin.Forms.Xaml
abstract class RootNode : ElementNode
{
protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver) : base(xmlType, xmlType.NamespaceUri, nsResolver)
protected RootNode(XmlType xmlType, IXmlNamespaceResolver nsResolver, int linenumber = -1, int lineposition = -1) : base(xmlType, xmlType.NamespaceUri, nsResolver, linenumber: linenumber, lineposition: lineposition)
{
}