未验证 提交 c5e8aa24 编写于 作者: J Jérôme Laban 提交者: GitHub

Merge pull request #11987 from Youssef1313/perf-xaml-gen

perf: Reduce string allocations in XamlFileParser
......@@ -9457,6 +9457,10 @@
<Member fullName="Windows.UI.Xaml.DependencyProperty Microsoft.UI.Xaml.Controls.ExpanderTemplateSettings.get_NegativeContentHeightProperty()" reason="Should not be public" />
<Member fullName="System.Void Microsoft.UI.Xaml.Controls.ExpanderTemplateSettings..ctor()" reason="Should not be public" />
<!-- BEGIN XamlFileParser performance updates -->
<Member fullName="System.Void Uno.Xaml.XamlXmlReader..ctor(System.Xml.XmlReader xmlReader, Uno.Xaml.XamlSchemaContext schemaContext, Uno.Xaml.XamlXmlReaderSettings settings)" reason="Adding parameter. These should not be used by user code" />
<!-- END XamlFileParser performance updates -->
<Member fullName="System.Void Uno.Foundation.Interop.JSObject.Dispatch(System.String handlePtr, System.String method, System.String parameters)" reason="First parameter changed from string to IntPtr for performance" />
</Methods>
</IgnoreSet>
......
......@@ -5,8 +5,8 @@
xmlns:local="using:UITests.Windows_Media"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:android="http://platform.uno/android"
xmlns:ios="http://platform.uno/android"
xmlns:android="http://platform.uno/android"
xmlns:ios="http://platform.uno/ios"
mc:Ignorable="d android ios"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......@@ -59,9 +59,9 @@ namespace MonoTests.Uno.Xaml
// bug #689548
var obj = new RootObjectInstanceTestClass ();
RootObjectInstanceTestClass result;
var rsettings = new XamlXmlReaderSettings ();
var xml = String.Format (@"<RootObjectInstanceTestClass Property=""Test"" xmlns=""clr-namespace:MonoTests.Uno.Xaml;assembly={0}""></RootObjectInstanceTestClass>", GetType ().Assembly.GetName ().Name);
using (var reader = new XamlXmlReader (new StringReader (xml), rsettings)) {
var wsettings = new XamlObjectWriterSettings ();
......@@ -71,7 +71,7 @@ namespace MonoTests.Uno.Xaml
result = (RootObjectInstanceTestClass) writer.Result;
}
}
Assert.AreEqual (obj, result, "#1");
Assert.AreEqual ("Test", obj.Property, "#2");
}
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......@@ -56,7 +56,7 @@ namespace MonoTests.Uno.Xaml
xm2 = new XamlMember (typeof (TestClass1).GetProperty ("TestProp1"), sctx);
xm3 = new XamlMember (typeof (TestClass1).GetProperty ("TestProp2"), sctx);
}
public class TestClass1
{
public TestClass1 ()
......@@ -80,7 +80,7 @@ namespace MonoTests.Uno.Xaml
public List<string> Baz { get; set; }
public string Ext { get; set; }
}
[Test]
public void SchemaContextNull ()
{
......@@ -621,7 +621,7 @@ namespace MonoTests.Uno.Xaml
xw.WriteStartObject(xt3);
xw.WriteStartMember(xm2);
xw.WriteNamespace(new NamespaceDeclaration("urn:foo", "y"));
// and here, NamespaceDeclaration is written as if it
// and here, NamespaceDeclaration is written as if it
// were another value object( unlike XamlXmlWriter)
// and rejects further value.
xw.WriteValue("foo");
......@@ -775,7 +775,7 @@ namespace MonoTests.Uno.Xaml
public void WriteAttachableProperty ()
{
Attached2 result = null;
var rsettings = new XamlXmlReaderSettings ();
using (var reader = new XamlXmlReader (new StringReader (String.Format (@"<Attached2 AttachedWrapper3.Property=""Test"" xmlns=""clr-namespace:MonoTests.Uno.Xaml;assembly={0}""></Attached2>", typeof (AttachedWrapper3).Assembly.GetName ().Name)), rsettings)) {
var wsettings = new XamlObjectWriterSettings ();
......@@ -787,7 +787,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual ("Test", result.Property, "#1");
}
[Test]
public void OnSetValueAndHandledFalse () // part of bug #3003
{
......@@ -819,7 +819,7 @@ namespace MonoTests.Uno.Xaml
var ret = xow.Result as TestClass3;
Assert.IsNotNull (ret.Nested, "#8");
}
[Test] // bug #3003 repro
[Ignore("")]
public void EventsAndProcessingOrder ()
......@@ -897,7 +897,7 @@ namespace MonoTests.Uno.Xaml
Assert.IsFalse (o.Child.Invoked, "#2");
Assert.IsFalse (o.Child.Descendant.Invoked, "#3");
}
[Test]
public void LookupCorrectEventBoundMethod2 ()
{
......@@ -906,13 +906,13 @@ namespace MonoTests.Uno.Xaml
XamlServices.Load(GetReader("LookupCorrectEvent2.xml"));
});
}
[Test]
public void LookupCorrectEventBoundMethod3 ()
{
XamlServices.Load (GetReader ("LookupCorrectEvent3.xml"));
}
// common use case based tests (to other readers/writers).
XamlReader GetReader (string filename)
......@@ -1144,7 +1144,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual (obj, des, "#1");
}
}
[Test]
public void Write_ArgumentAttributed ()
{
......@@ -1295,7 +1295,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual ("foo", des, "#1");
}
}
[Test]
public void Write_PropertyDefinition ()
{
......@@ -1307,7 +1307,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual (XamlLanguage.String, des.Type, "#3");
}
}
[Test]
[Ignore ("this still does not give successful deserialization result - should there be any way?")]
public void Write_StaticExtensionWrapper ()
......@@ -1319,7 +1319,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual ("Foo", des.Param.Member, "#2");
}
}
[Test]
[Ignore ("this still does not give successful deserialization result - should there be any way?")]
public void Write_TypeExtensionWrapper ()
......@@ -1332,7 +1332,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual (String.Empty, des.Param.TypeName, "#2");
}
}
[Test]
public void Write_NamedItems ()
{
......@@ -1355,7 +1355,7 @@ namespace MonoTests.Uno.Xaml
Assert.AreEqual (des, des.References [0].References [0], "#5");
}
}
[Test]
public void Write_NamedItems2 ()
{
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......@@ -1233,7 +1233,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_TextLiteral()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1280,7 +1280,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_WhiteSpacePreservation()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1289,7 +1289,7 @@ namespace MonoTests.Uno.Xaml
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = XamlLanguage.Base.ToString() },
new SequenceItem { NodeType = XamlNodeType.Value, Value = "", },
new SequenceItem { NodeType = XamlNodeType.EndMember, },
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml}_UnknownContent", },
new SequenceItem { NodeType = XamlNodeType.StartObject, TypeName = "{http://schemas.microsoft.com/winfx/2006/xaml/presentation}TextBlock"},
new SequenceItem { NodeType = XamlNodeType.StartMember, MemberType = "{http://schemas.microsoft.com/winfx/2006/xaml}_UnknownContent", },
......@@ -1379,7 +1379,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_CustomAttachedProperty()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1407,7 +1407,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_xBind()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1442,7 +1442,7 @@ namespace MonoTests.Uno.Xaml
while (r.Read()) { }
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1468,7 +1468,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_RunSpace01()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -1509,7 +1509,7 @@ namespace MonoTests.Uno.Xaml
[Test]
public void Read_RunSpace02()
{
var sequence = new SequenceItem[]
var sequence = new SequenceItem[]
{
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
new SequenceItem { NodeType = XamlNodeType.NamespaceDeclaration, },
......@@ -2096,7 +2096,7 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("TestClass4.xml");
WriteNullMemberAsObject (r, null);
}
[Test]
public void StaticMember ()
{
......@@ -2110,7 +2110,7 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("String.xml");
Skip (r);
}
[Test]
public void Skip2 ()
{
......@@ -2134,56 +2134,56 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("NonPrimitive.xml");
Read_NonPrimitive (r);
}
[Test]
public void Read_TypeExtension ()
{
var r = GetReader ("Type.xml");
Read_TypeOrTypeExtension (r, null, XamlLanguage.Type.GetMember ("Type"));
}
[Test]
public void Read_Type2 ()
{
var r = GetReader ("Type2.xml");
Read_TypeOrTypeExtension2 (r, null, XamlLanguage.Type.GetMember ("Type"));
}
[Test]
public void Read_Reference ()
{
var r = GetReader ("Reference.xml");
Read_Reference (r);
}
[Test]
public void Read_Null ()
{
var r = GetReader ("NullExtension.xml");
Read_NullOrNullExtension (r, null);
}
[Test]
public void Read_StaticExtension ()
{
var r = GetReader ("StaticExtension.xml");
Read_StaticExtension (r, XamlLanguage.Static.GetMember ("Member"));
}
[Test]
public void Read_ListInt32 ()
{
var r = GetReader ("List_Int32.xml", ignoreWhitespace: true);
Read_ListInt32 (r, null, new int [] {5, -3, int.MaxValue, 0}.ToList ());
}
[Test]
public void Read_ListInt32_2 ()
{
var r = GetReader ("List_Int32_2.xml");
Read_ListInt32 (r, null, new int [0].ToList ());
}
[Test]
public void Read_ListType ()
{
......@@ -2204,14 +2204,14 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("ArrayList.xml", ignoreWhitespace: true);
Read_ArrayList (r);
}
[Test]
public void Read_Array ()
{
var r = GetReader ("ArrayExtension.xml", ignoreWhitespace: true);
Read_ArrayOrArrayExtensionOrMyArrayExtension (r, null, typeof (ArrayExtension));
}
[Test]
public void Read_MyArrayExtension ()
{
......@@ -2232,28 +2232,28 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("MyExtension.xml");
Read_CustomMarkupExtension (r);
}
[Test]
public void Read_CustomMarkupExtension2 ()
{
var r = GetReader ("MyExtension2.xml");
Read_CustomMarkupExtension2 (r);
}
[Test]
public void Read_CustomMarkupExtension3 ()
{
var r = GetReader ("MyExtension3.xml");
Read_CustomMarkupExtension3 (r);
}
[Test]
public void Read_CustomMarkupExtension4 ()
{
var r = GetReader ("MyExtension4.xml");
Read_CustomMarkupExtension4 (r);
}
[Test]
public void Read_CustomMarkupExtension6 ()
{
......@@ -2278,7 +2278,7 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("Dictionary_String_Double.xml", ignoreWhitespace: true);
Read_Dictionary (r);
}
[Test]
public void Read_Dictionary2 ()
{
......@@ -2288,7 +2288,7 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("Dictionary_String_Type_2.xml", ignoreWhitespace: true);
Read_Dictionary2 (r, XamlLanguage.Type.GetMember ("Type"));
}
[Test]
[Ignore("Not supported for UWP XAML markup extensions")]
public void PositionalParameters2 ()
......@@ -2303,14 +2303,14 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("ComplexPositionalParameterWrapper.xml");
ComplexPositionalParameters (r);
}
[Test]
public void Read_ListWrapper ()
{
var r = GetReader ("ListWrapper.xml", ignoreWhitespace: true);
Read_ListWrapper (r);
}
[Test]
public void Read_ListWrapper2 () // read-write list member.
{
......@@ -2491,7 +2491,7 @@ namespace MonoTests.Uno.Xaml
var r = GetReader ("DirectDictionaryContainer2.xml", ignoreWhitespace: true);
Read_DirectDictionaryContainer2 (r);
}
[Test]
public void Read_ContentPropertyContainer ()
{
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......
......@@ -8,10 +8,10 @@
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
......@@ -32,6 +32,39 @@ using Pair = System.Collections.Generic.KeyValuePair<Uno.Xaml.XamlMember,string>
namespace Uno.Xaml
{
public readonly struct IsIncludedResult : IEquatable<IsIncludedResult>
{
public static IsIncludedResult Default { get; } = new IsIncludedResult(isIncluded: null, disableCaching: false);
public static IsIncludedResult ForceExclude { get; } = new IsIncludedResult(isIncluded: false, disableCaching: false);
public static IsIncludedResult ForceInclude { get; } = new IsIncludedResult(isIncluded: true, disableCaching: false);
public static IsIncludedResult ForceIncludeWithCacheDisabled { get; } = new IsIncludedResult(isIncluded: true, disableCaching: true);
public bool? IsIncluded { get; }
public bool DisableCaching { get; }
private IsIncludedResult(bool? isIncluded, bool disableCaching)
{
IsIncluded = isIncluded;
DisableCaching = disableCaching;
}
public override bool Equals(object obj) => obj is IsIncludedResult result && Equals(result);
public bool Equals(IsIncludedResult other) => IsIncluded == other.IsIncluded && DisableCaching == other.DisableCaching;
public override int GetHashCode()
{
var hashCode = 676255761;
hashCode = hashCode * -1521134295 + IsIncluded.GetHashCode();
hashCode = hashCode * -1521134295 + DisableCaching.GetHashCode();
return hashCode;
}
public static bool operator ==(IsIncludedResult left, IsIncludedResult right) => left.Equals(right);
public static bool operator !=(IsIncludedResult left, IsIncludedResult right) => !(left == right);
}
public delegate IsIncludedResult IsIncluded(string localName, string namespaceUri);
public class XamlXmlReader : XamlReader, IXamlLineInfo
{
#region constructors
......@@ -113,16 +146,19 @@ namespace Uno.Xaml
{
}
public XamlXmlReader (XmlReader xmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings)
// Uno specific: includeXamlNamespaces and excludeXamlNamespaces are Uno specific.
public XamlXmlReader (XmlReader xmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings, IsIncluded isIncluded = null)
{
parser = new XamlXmlParser (xmlReader, schemaContext, settings);
parser = new XamlXmlParser (xmlReader, schemaContext, settings, isIncluded ?? ((_, _) => IsIncludedResult.Default));
}
#endregion
XamlXmlParser parser;
IEnumerator<XamlXmlNodeInfo> iter;
public bool DisableCaching => parser.DisableCaching;
public bool PreserveWhitespace => parser.Reader.XmlSpace == XmlSpace.Preserve;
public bool HasLineInfo {
......@@ -175,7 +211,7 @@ namespace Uno.Xaml
return iter.Current.NodeType != XamlNodeType.None;
}
}
struct XamlXmlNodeInfo
{
public XamlXmlNodeInfo (XamlNodeType nodeType, object nodeValue, IXmlLineInfo lineInfo)
......@@ -192,17 +228,20 @@ namespace Uno.Xaml
LinePosition = 0;
}
}
public bool HasLineInfo;
public int LineNumber;
public int LinePosition;
public XamlNodeType NodeType;
public object NodeValue;
}
class XamlXmlParser
{
public XamlXmlParser (XmlReader xmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings)
// Uno specific
private readonly IsIncluded _isIncluded;
public XamlXmlParser (XmlReader xmlReader, XamlSchemaContext schemaContext, XamlXmlReaderSettings settings, IsIncluded isIncluded)
{
if (xmlReader == null)
throw new ArgumentNullException ("xmlReader");
......@@ -223,8 +262,10 @@ namespace Uno.Xaml
r = XmlReader.Create (xmlReader, xrs);
line_info = r as IXmlLineInfo;
xaml_namespace_resolver = new NamespaceResolver (r as IXmlNamespaceResolver);
_isIncluded = isIncluded;
}
XmlReader r;
IXmlLineInfo line_info;
XamlSchemaContext sctx;
......@@ -252,7 +293,7 @@ namespace Uno.Xaml
yield return xi;
yield return Node (XamlNodeType.None, null);
}
// Note that it could return invalid (None) node to tell the caller that it is not really an object element.
IEnumerable<XamlXmlNodeInfo> ReadObjectElement (XamlType parentType, XamlMember currentMember)
{
......@@ -279,7 +320,7 @@ namespace Uno.Xaml
var sti = GetStartTagInfo ();
using (PushIgnorables(sti.Members))
{
if (IsIgnored(r.Prefix))
if (IsIgnored(r.Prefix, r.NamespaceURI, out _))
{
r.Skip();
yield break;
......@@ -511,16 +552,16 @@ namespace Uno.Xaml
break;
default:
if (IsIgnored(r.Prefix))
if (IsIgnored(r.Prefix, r.NamespaceURI, out var shouldTreatAsDefaultNamespace))
{
continue;
}
if (r.NamespaceURI == String.Empty || r.NamespaceURI == r.LookupNamespace("") ) {
if (r.NamespaceURI == String.Empty || r.NamespaceURI == r.LookupNamespace("") || shouldTreatAsDefaultNamespace) {
atts.Add (r.LocalName, r.Value);
continue;
}
if (r.NamespaceURI.StartsWith("using:", StringComparison.Ordinal) || r.NamespaceURI.StartsWith("#using:", StringComparison.Ordinal)) {
if (r.NamespaceURI.StartsWith("using:", StringComparison.Ordinal) || r.NamespaceURI.Contains("#using:")) {
atts.Add (r.Name, r.Value);
continue;
}
......@@ -683,7 +724,7 @@ namespace Uno.Xaml
// member element, implicit member, children via content property, or value
IEnumerable<XamlXmlNodeInfo> ReadMemberElement (XamlType parentType, XamlType xt)
{
if (IsIgnored(r.Prefix))
if (IsIgnored(r.Prefix, r.NamespaceURI, out _))
{
r.Skip();
yield break;
......@@ -776,7 +817,7 @@ namespace Uno.Xaml
}
}
else
{
{
foreach (var ni in ReadCollectionItems(xt, xm))
yield return ni;
}
......@@ -819,7 +860,7 @@ namespace Uno.Xaml
throw new Exception("should not happen");
yield return ni;
}
}
}
}
}
......@@ -838,8 +879,8 @@ namespace Uno.Xaml
member = XamlLanguage.UnknownContent;
}
for (
r.MoveToContent();
for (
r.MoveToContent();
r.NodeType != XmlNodeType.EndElement && r.NodeType != XmlNodeType.None && !r.Name.Contains(".");
// nothing
) {
......@@ -891,6 +932,8 @@ namespace Uno.Xaml
get { return line_info != null && line_info.HasLineInfo () ? line_info.LinePosition : 0; }
}
public bool DisableCaching { get; private set; }
private IDisposable PushIgnorables(List<Pair> members)
{
var ignorable = members.FirstOrDefault(a => a.Key == XamlLanguage.Ignorable);
......@@ -903,8 +946,23 @@ namespace Uno.Xaml
return null;
}
private bool IsIgnored(string localName)
private bool IsIgnored(string localName, string namespaceUri, out bool shouldTreatAsDefaultNamespace)
{
var result = _isIncluded(localName, namespaceUri);
var isIncluded = result.IsIncluded;
DisableCaching |= result.DisableCaching;
if (isIncluded == true)
{
shouldTreatAsDefaultNamespace = true;
return false;
}
shouldTreatAsDefaultNamespace = false;
if (isIncluded == false)
{
return true;
}
if (ignorables.SelectMany(v => v).Contains(localName))
{
return true;
......
......@@ -398,7 +398,10 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
var resourceDetailsCollection = BuildResourceDetails(_generatorContext.CancellationToken);
TryGenerateUnoResourcesKeyAttribute(resourceDetailsCollection);
var filesFull = new XamlFileParser(_excludeXamlNamespaces, _includeXamlNamespaces, _metadataHelper)
var excludeXamlNamespaces = _excludeXamlNamespaces.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var includeXamlNamespaces = _includeXamlNamespaces.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var filesFull = new XamlFileParser(_excludeXamlNamespaces, _includeXamlNamespaces, excludeXamlNamespaces, includeXamlNamespaces, _metadataHelper)
.ParseFiles(_xamlSourceFiles, _projectDirectory, _generatorContext.CancellationToken);
var xamlTypeToXamlTypeBaseMap = new ConcurrentDictionary<INamedTypeSymbol, XamlRedirection.XamlType>();
......@@ -470,7 +473,8 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
generatorContext: _generatorContext,
xamlResourcesTrimming: _xamlResourcesTrimming,
generationRunFileInfo: generationRunInfo.GetRunFileInfo(file.UniqueID),
xamlTypeToXamlTypeBaseMap: xamlTypeToXamlTypeBaseMap
xamlTypeToXamlTypeBaseMap: xamlTypeToXamlTypeBaseMap,
includeXamlNamespaces: includeXamlNamespaces
).GenerateFile()
)).ToList();
......
......@@ -622,7 +622,23 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
}
var nsName = GetTrimmedNamespace(trimmedNamespace);
if (_metadataHelper.FindTypeByFullName(nsName + "." + type.Name) is INamedTypeSymbol namedType)
if (nsName.IndexOf("#using:", StringComparison.Ordinal) is int indexOfHashUsing && indexOfHashUsing > -1)
{
if (SearchClrNamespaces(type.Name) is INamedTypeSymbol symbolFromCLRNamespace)
{
return symbolFromCLRNamespace;
}
var hashUsingNamespaces = nsName.Substring(indexOfHashUsing + "#using:".Length).Split(';');
foreach (var hashUsingNamespace in hashUsingNamespaces)
{
if (_metadataHelper.FindTypeByFullName(hashUsingNamespace + "." + type.Name) is INamedTypeSymbol namedType)
{
return namedType;
}
}
}
else if (_metadataHelper.FindTypeByFullName(nsName + "." + type.Name) is INamedTypeSymbol namedType)
{
return namedType;
}
......@@ -645,6 +661,23 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
return null;
}
private INamedTypeSymbol? SearchClrNamespaces(string name)
{
if (_clrNamespaces != null)
{
// Search first using the default namespace
foreach (var clrNamespace in _clrNamespaces)
{
if (_metadataHelper.FindTypeByFullName(clrNamespace + "." + name) is INamedTypeSymbol type)
{
return type;
}
}
}
return null;
}
private INamedTypeSymbol GetType(string name)
{
var type = _findType!(name);
......@@ -687,34 +720,26 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
// We should be returning null here, but we fallback to fuzzy matching if enabled.
return SearchWithFuzzyMatching(fields[1]);
}
else if (ns.Namespace.Equals("http://schemas.microsoft.com/winfx/2006/xaml/presentation", StringComparison.Ordinal))
var indexOfQuestionMark = ns.Namespace.IndexOf('?');
var namespaceUrl = ns.Namespace;
if (indexOfQuestionMark > -1)
{
return SearchClrNamespaces(fields[1]);
namespaceUrl = ns.Namespace.Substring(0, indexOfQuestionMark);
}
else if (ns.Namespace.StartsWith("#using:", StringComparison.Ordinal))
{
// We are dealing with a namespace on the form `xmlns:android="http://platform.uno/android#using:TestNS;TestNS2"`
// In this case, we search both the default namespaces and the user-specified namespaces.
// This code path is about the new "#using" syntax, so we never fallback to fuzzy matching here.
var firstResult = SearchClrNamespaces(fields[1]);
if (firstResult is not null)
{
return firstResult;
}
var userSpecifiedNamespaces = ns.Namespace.Substring("#using:".Length).Split(';');
foreach (var userSpecifiedNamespace in userSpecifiedNamespaces)
{
if (_metadataHelper.FindTypeByFullName(userSpecifiedNamespace + "." + fields[1]) is INamedTypeSymbol symbolFromUserSpecifiedNamespaces)
{
return symbolFromUserSpecifiedNamespaces;
}
}
if (namespaceUrl.Equals("http://schemas.microsoft.com/winfx/2006/xaml/presentation", StringComparison.Ordinal))
{
return SearchClrNamespaces(fields[1]);
}
return null;
var nsName = GetTrimmedNamespace(namespaceUrl);
if (namespaceUrl == nsName && _includeXamlNamespaces.Contains(ns.Prefix))
{
// For XAML included namespaces (e.g, android) where we don't have "using:" in the url, assume the default namespace.
return SearchClrNamespaces(fields[1]);
}
var nsName = GetTrimmedNamespace(ns.Namespace);
name = nsName + "." + fields[1];
if (_metadataHelper.FindTypeByFullName(name) is INamedTypeSymbol namedTypeSymbol1)
......@@ -752,23 +777,6 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
return SearchWithFuzzyMatching(name);
INamedTypeSymbol? SearchClrNamespaces(string name)
{
if (_clrNamespaces != null)
{
// Search first using the default namespace
foreach (var clrNamespace in _clrNamespaces)
{
if (_metadataHelper.FindTypeByFullName(clrNamespace + "." + name) is INamedTypeSymbol type)
{
return type;
}
}
}
return null;
}
INamedTypeSymbol? SearchWithFuzzyMatching(string name)
{
if (!_enableFuzzyMatching)
......
......@@ -143,6 +143,8 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
private readonly IDictionary<INamedTypeSymbol, XamlType> _xamlTypeToXamlTypeBaseMap;
private readonly string[] _includeXamlNamespaces;
/// <summary>
/// Information about types used in .Apply() scenarios
/// </summary>
......@@ -223,7 +225,8 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
GeneratorExecutionContext generatorContext,
bool xamlResourcesTrimming,
GenerationRunFileInfo generationRunFileInfo,
IDictionary<INamedTypeSymbol, XamlType> xamlTypeToXamlTypeBaseMap)
IDictionary<INamedTypeSymbol, XamlType> xamlTypeToXamlTypeBaseMap,
string[] includeXamlNamespaces)
{
Generation = generation;
_fileDefinition = file;
......@@ -251,6 +254,7 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
_xamlResourcesTrimming = xamlResourcesTrimming;
_generationRunFileInfo = generationRunFileInfo;
_xamlTypeToXamlTypeBaseMap = xamlTypeToXamlTypeBaseMap;
_includeXamlNamespaces = includeXamlNamespaces;
InitCaches();
......@@ -1391,7 +1395,7 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
var propertyName = GetInitializerNameForResourceKey(index);
if (_topLevelQualifiedKeys.ContainsKey((theme, key)))
{
throw new InvalidOperationException($"Dictionary Item {resource?.Type?.Name} has duplicate key `{key}` {(theme != null ? $" in theme {theme}" : "")}.");
throw new InvalidOperationException($"Dictionary Item {resource.Type?.Name} has duplicate key `{key}` {(theme != null ? $" in theme {theme}" : "")}.");
}
var isStaticResourceAlias = resource.Type.Name == "StaticResource";
if (!isStaticResourceAlias)
......@@ -2408,7 +2412,7 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
{
var firstChild = implicitContentChild.Objects.First();
var elementType = topLevelControlSymbol ?? throw new InvalidOperationException("The type {0} could not be found".InvariantCultureFormat(topLevelControl.Type)); ;
var elementType = topLevelControlSymbol ?? throw new InvalidOperationException("The type {0} could not be found".InvariantCultureFormat(topLevelControl.Type));
var contentProperty = FindContentProperty(elementType);
writer.AppendLineInvariantIndented("{0}{1} = ",
......
......@@ -18,10 +18,6 @@ using Uno.UI.SourceGenerators.XamlGenerator.Utils;
using Uno.Roslyn;
using Windows.Foundation.Metadata;
#if NETFRAMEWORK
using GeneratorExecutionContext = Uno.SourceGeneration.GeneratorExecutionContext;
#endif
namespace Uno.UI.SourceGenerators.XamlGenerator
{
internal partial class XamlFileParser
......@@ -41,13 +37,13 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
private int _depth;
public XamlFileParser(string excludeXamlNamespaces, string includeXamlNamespaces, RoslynMetadataHelper roslynMetadataHelper)
public XamlFileParser(string excludeXamlNamespacesProperty, string includeXamlNamespacesProperty, string[] excludeXamlNamespaces, string[] includeXamlNamespaces, RoslynMetadataHelper roslynMetadataHelper)
{
_excludeXamlNamespacesProperty = excludeXamlNamespaces;
_excludeXamlNamespaces = excludeXamlNamespaces.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
_excludeXamlNamespacesProperty = excludeXamlNamespacesProperty;
_excludeXamlNamespaces = excludeXamlNamespaces;
_includeXamlNamespacesProperty = includeXamlNamespaces;
_includeXamlNamespaces = includeXamlNamespaces.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
_includeXamlNamespacesProperty = includeXamlNamespacesProperty;
_includeXamlNamespaces = includeXamlNamespaces;
_metadataHelper = roslynMetadataHelper;
}
......@@ -77,6 +73,8 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
private static void ScavengeCache()
{
// DateTimeOffset.Now might be expensive.
// Investigate if using Environment.TickCount can work and is faster.
_cachedFiles.Remove(kvp => DateTimeOffset.Now - kvp.Value.LastTimeUsed > _cacheEntryLifetime);
}
......@@ -105,23 +103,23 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
ScavengeCache();
// Initialize the reader using an empty context, because when the tasl
// is run under the BeforeCompile in VS IDE, the loaded assemblies are used
// is run under the BeforeCompile in VS IDE, the loaded assemblies are used
// to interpret the meaning of objects, which is not correct in Uno.UI context.
var context = new XamlSchemaContext(Enumerable.Empty<Assembly>());
// Force the line info, otherwise it will be enabled only when the debugger is attached.
var settings = new XamlXmlReaderSettings() { ProvideLineInfo = true };
(XmlReader document, bool disableCaching) = ApplyIgnorables(file, sourceText, cancellationToken);
XmlReader document = RewriteForXBind(sourceText);
using (var reader = new XamlXmlReader(document, context, settings))
using (var reader = new XamlXmlReader(document, context, settings, IsIncluded))
{
if (reader.Read())
{
cancellationToken.ThrowIfCancellationRequested();
var xamlFileDefinition = Visit(reader, file.Path, targetFilePath);
if (!disableCaching)
if (!reader.DisableCaching)
{
_cachedFiles[cachedFileKey] = new CachedFile(DateTimeOffset.Now, xamlFileDefinition);
}
......@@ -150,268 +148,80 @@ namespace Uno.UI.SourceGenerators.XamlGenerator
}
}
private (XmlReader Reader, bool DisableCaching) ApplyIgnorables(AdditionalText file, SourceText sourceText, CancellationToken cancellationToken)
private XmlReader RewriteForXBind(SourceText sourceText)
{
var originalString = sourceText.ToString();
StringBuilder adjusted;
var document = new XmlDocument();
document.LoadXml(originalString);
var (ignorables, shouldCreateIgnorable) = FindIgnorables(document);
var conditionals = FindConditionals(document);
shouldCreateIgnorable |= conditionals.ExcludedConditionals.Count > 0;
var hasxBind = originalString.Contains("{x:Bind", StringComparison.Ordinal);
if (ignorables == null && !shouldCreateIgnorable && !hasxBind)
if (!hasxBind)
{
// No need to modify file
return (XmlReader.Create(new StringReader(originalString)), conditionals.DisableCaching);
}
var originalIgnorables = ignorables?.Value ?? "";
var ignoredNs = originalIgnorables.Split(' ');
var newIgnored = ignoredNs
.Except(_includeXamlNamespaces)
.Concat(_excludeXamlNamespaces.Where(n => document.DocumentElement is { } documentElement && !documentElement.GetNamespaceOfPrefix(n).IsNullOrEmpty()))
.Concat(conditionals.ExcludedConditionals.Select(a => a.LocalName))
.ToArray();
var newIgnoredFlat = newIgnored.JoinBy(" ");
if (ignorables != null)
{
ignorables.Value = newIgnoredFlat;
#if DEBUG
Console.WriteLine("Ignorable XAML namespaces: {0} for {1}", ignorables.Value, file.Path);
#endif
adjusted = new StringBuilder(originalString);
// change the namespaces using textreplace, to keep the formatting and have proper
// line/position reporting.
adjusted
.Replace(
"Ignorable=\"{0}\"".InvariantCultureFormat(originalIgnorables),
"Ignorable=\"{0}\"".InvariantCultureFormat(ignorables.Value)
);
return XmlReader.Create(new StringReader(originalString));
}
else
{
// No existing Ignorable node, create one
var targetLine = sourceText.Lines.Select(l => sourceText.ToString(l.Span)).First(l => !l.IsNullOrWhiteSpace() && !l.Trim().StartsWith("<!", StringComparison.Ordinal))!;
if (targetLine.EndsWith(">", StringComparison.Ordinal))
{
targetLine = targetLine.TrimEnd(">");
}
var mcName = document.DocumentElement?
.Attributes
.Cast<XmlAttribute>()
.FirstOrDefault(a => a.Prefix == "xmlns" && a.Value == "http://schemas.openxmlformats.org/markup-compatibility/2006")
?.LocalName;
var mcString = "";
if (mcName == null)
{
mcName = "mc";
mcString = " xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"";
}
var replacement = "{0}{1} {2}:Ignorable=\"{3}\"".InvariantCultureFormat(targetLine, mcString, mcName, newIgnoredFlat);
adjusted = ReplaceFirst(
originalString,
targetLine,
replacement
);
}
// Replace the ignored namespaces with unique urns so that same urn that are placed in Ignored attribute
// are ignored independently.
foreach (var n in newIgnored)
{
adjusted
.Replace(
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement?.GetNamespaceOfPrefix(n)),
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, Guid.NewGuid())
);
}
// Put all the included namespaces in the same default namespace, so that the properties get their
// DeclaringType properly set.
foreach (var n in _includeXamlNamespaces)
{
if (document.DocumentElement != null)
{
var originalPrefix = document.DocumentElement.GetNamespaceOfPrefix(n);
var indexOfUsingColon = originalPrefix.IndexOf("using:", StringComparison.Ordinal);
if (indexOfUsingColon == -1)
{
// There is no "using:" in the namespace. So assume the default namespace
adjusted
.Replace(
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, originalPrefix),
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, document.DocumentElement.GetNamespaceOfPrefix(""))
);
}
else if (indexOfUsingColon > 0 && originalPrefix[indexOfUsingColon - 1] == '#')
{
// We have "#using:", we want to keep it.
adjusted
.Replace(
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, originalPrefix),
"xmlns:{0}=\"{1}\"".InvariantCultureFormat(n, originalPrefix.Substring(indexOfUsingColon - 1))
);
}
}
}
foreach (var includedCond in conditionals.IncludedConditionals)
{
var valueSplit = includedCond.Value.Split('?');
// Strip the conditional part, so the namespace can be parsed correctly by the Xaml reader
adjusted
.Replace(
includedCond.OuterXml,
"{0}=\"{1}\"".InvariantCultureFormat(includedCond.Name, valueSplit[0])
);
}
if (hasxBind)
{
// Apply replacements to avoid having issues with the XAML parser which does not
// support quotes in positional markup extensions parameters.
// Note that the UWP preprocessor does not need to apply those replacements as the
// x:Bind expressions are being removed during the first phase and replaced by "connections".
adjusted = new(XBindExpressionParser.RewriteDocumentPaths(adjusted.ToString()));
}
// Apply replacements to avoid having issues with the XAML parser which does not
// support quotes in positional markup extensions parameters.
// Note that the UWP preprocessor does not need to apply those replacements as the
// x:Bind expressions are being removed during the first phase and replaced by "connections".
var adjusted = XBindExpressionParser.RewriteDocumentPaths(originalString);
return (XmlReader.Create(new StringReader(adjusted.ToString())), conditionals.DisableCaching);
return XmlReader.Create(new StringReader(adjusted));
}
private static StringBuilder ReplaceFirst(string targetString, string oldValue, string newValue)
private __uno::Uno.Xaml.IsIncludedResult IsIncluded(string localName, string namespaceUri)
{
var index = targetString.IndexOf(oldValue, StringComparison.InvariantCulture);
if (index < 0)
if (_includeXamlNamespaces.Contains(localName))
{
throw new InvalidOperationException();
return __uno::Uno.Xaml.IsIncludedResult.ForceInclude;
}
var result = new StringBuilder(targetString.Length + newValue.Length);
result.Append(targetString, 0, index);
result.Append(newValue);
var secondBlockStart = index + oldValue.Length;
result.Append(targetString, secondBlockStart, targetString.Length - secondBlockStart);
return result;
}
private (XmlNode? Ignorables, bool ShouldCreateIgnorable) FindIgnorables(XmlDocument document)
{
var ignorables = document.DocumentElement?.Attributes.GetNamedItem("Ignorable", "http://schemas.openxmlformats.org/markup-compatibility/2006") as XmlAttribute;
var excludeNamespaces = _excludeXamlNamespaces
.Select(n => new { Name = n, Namespace = document.DocumentElement?.GetNamespaceOfPrefix(n) })
.Where(n => !n.Namespace.IsNullOrEmpty());
var shouldCreateIgnorable = false;
foreach (var nspace in excludeNamespaces)
else if (_excludeXamlNamespaces.Contains(localName))
{
var excludeNodes = document
.DocumentElement
?.SelectNodes("//* | //@*")
?.OfType<XmlNode>()
.Where(e => e.Prefix == nspace.Name);
return __uno::Uno.Xaml.IsIncludedResult.ForceExclude;
}
if (ignorables == null && (excludeNodes?.Any() ?? false))
{
shouldCreateIgnorable = true;
}
var valueSplit = namespaceUri.Split('?');
if (valueSplit.Length != 2)
{
// Not a (valid) conditional
return __uno::Uno.Xaml.IsIncludedResult.Default;
}
return (ignorables, shouldCreateIgnorable);
}
var elements = valueSplit[1].Split('(', ',', ')');
/// <summary>
/// Returns those XAML namespace definitions for which a conditional is set, grouped by those for which the conditional returns true and
/// should be included, and those for which it returns fales and should be excluded.
/// </summary>
private (List<XmlAttribute> IncludedConditionals, List<XmlAttribute> ExcludedConditionals, bool DisableCaching) FindConditionals(XmlDocument document)
{
var disableCaching = false;
var included = new List<XmlAttribute>();
var excluded = new List<XmlAttribute>();
var methodName = elements[0];
foreach (XmlAttribute attr in document.DocumentElement!.Attributes)
switch (methodName)
{
if (attr.Prefix != "xmlns")
{
// Not a namespace
continue;
}
var valueSplit = attr.Value.Split('?');
if (valueSplit.Length != 2)
{
// Not a (valid) conditional
continue;
}
(bool? shouldInclude, bool disableCaching1) = ShouldInclude();
disableCaching = disableCaching || disableCaching1;
if (shouldInclude.HasValue)
{
if (shouldInclude.GetValueOrDefault())
{
included.Add(attr);
}
else
case nameof(ApiInformation.IsApiContractPresent):
case nameof(ApiInformation.IsApiContractNotPresent):
if (elements.Length < 4 || !ushort.TryParse(elements[2].Trim(), out var majorVersion))
{
excluded.Add(attr);
throw new InvalidOperationException($"Syntax error while parsing conditional namespace expression {namespaceUri}");
}
}
(bool? ShouldInclude, bool DisableCaching) ShouldInclude()
{
var elements = valueSplit[1].Split('(', ',', ')');
var methodName = elements[0];
switch (methodName)
var isIncluded1 = methodName == nameof(ApiInformation.IsApiContractPresent) ?
ApiInformation.IsApiContractPresent(elements[1], majorVersion) :
ApiInformation.IsApiContractNotPresent(elements[1], majorVersion);
return isIncluded1
? __uno::Uno.Xaml.IsIncludedResult.ForceInclude
: __uno::Uno.Xaml.IsIncludedResult.ForceExclude;
case nameof(ApiInformation.IsTypePresent):
case nameof(ApiInformation.IsTypeNotPresent):
if (elements.Length < 2)
{
case nameof(ApiInformation.IsApiContractPresent):
case nameof(ApiInformation.IsApiContractNotPresent):
if (elements.Length < 4 || !ushort.TryParse(elements[2].Trim(), out var majorVersion))
{
throw new InvalidOperationException($"Syntax error while parsing conditional namespace expression {attr.Value}");
}
return (methodName == nameof(ApiInformation.IsApiContractPresent) ?
ApiInformation.IsApiContractPresent(elements[1], majorVersion) :
ApiInformation.IsApiContractNotPresent(elements[1], majorVersion), false);
case nameof(ApiInformation.IsTypePresent):
case nameof(ApiInformation.IsTypeNotPresent):
if (elements.Length < 2)
{
throw new InvalidOperationException($"Syntax error while parsing conditional namespace expression {attr.Value}");
}
var expectedType = elements[1];
return (methodName == nameof(ApiInformation.IsTypePresent) ?
ApiInformation.IsTypePresent(elements[1], _metadataHelper) :
ApiInformation.IsTypeNotPresent(elements[1], _metadataHelper), true);
default:
return (null, false);// TODO: support IsPropertyPresent
throw new InvalidOperationException($"Syntax error while parsing conditional namespace expression {namespaceUri}");
}
}
var expectedType = elements[1];
var isIncluded2 = methodName == nameof(ApiInformation.IsTypePresent) ?
ApiInformation.IsTypePresent(elements[1], _metadataHelper) :
ApiInformation.IsTypeNotPresent(elements[1], _metadataHelper);
return isIncluded2
? __uno::Uno.Xaml.IsIncludedResult.ForceIncludeWithCacheDisabled
: __uno::Uno.Xaml.IsIncludedResult.ForceExclude;
default:
return __uno::Uno.Xaml.IsIncludedResult.Default; // TODO: support IsPropertyPresent
}
return (included, excluded, disableCaching);
}
private XamlFileDefinition Visit(XamlXmlReader reader, string file, string targetFilePath)
......
......@@ -9,11 +9,13 @@ namespace Uno.UI.SourceGenerators.XamlGenerator.XamlRedirection
{
private __uno::Uno.Xaml.XamlXmlReader _unoReader;
public XamlXmlReader(XmlReader document, XamlSchemaContext context, XamlXmlReaderSettings settings)
public XamlXmlReader(XmlReader document, XamlSchemaContext context, XamlXmlReaderSettings settings, __uno::Uno.Xaml.IsIncluded isIncluded)
{
_unoReader = new __uno::Uno.Xaml.XamlXmlReader(document, context.UnoInner, settings.UnoInner);
_unoReader = new __uno::Uno.Xaml.XamlXmlReader(document, context.UnoInner, settings.UnoInner, isIncluded);
}
public bool DisableCaching => _unoReader.DisableCaching;
public XamlNodeType NodeType => Convert(_unoReader.NodeType);
private XamlNodeType Convert(__uno::Uno.Xaml.XamlNodeType source)
......
......@@ -10,6 +10,7 @@
xmlns:contract1NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,1)"
xmlns:contract9999Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 9999)"
xmlns:contract9999NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,9999)"
xmlns:net461="http://uno.ui/net461"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
views:MyBehavior.Bulbousness="{StaticResource DoubleOrNothing}">
......@@ -102,10 +103,15 @@
x:FieldModifier="public"
contract9999Present:Text="Contract"
contract9999NotPresent:Text="Not Contract" />
<TextBlock x:Name="testConditionalTextBlock3"
x:FieldModifier="public"
net461:Text="Hello tests!" />
<TextBlock x:Name="testSubclassedDictionaryTextBlock"
x:FieldModifier="public"
Text="{StaticResource ProblemFreePhilosophy}" />
<ext:MyTextBox x:Name="myExtTextBox"
x:FieldModifier="public" />
</Grid>
</Page>
......@@ -62,5 +62,13 @@ namespace Uno.UI.Tests.Windows_UI_Xaml
Assert.AreEqual("Is not present", page.tilemixednotpresentTextBlock.Text);
#endif
}
[TestMethod]
public void When_Conditional_Platform_For_Property()
{
var page = new Test_Page();
var tb = page.testConditionalTextBlock3;
Assert.AreEqual("Hello tests!", tb.Text);
}
}
}
......@@ -346,7 +346,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uno.UI.Svg.Skia", "AddIns\U
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uno.UI.Svg.Reference", "AddIns\Uno.UI.Svg\Uno.UI.Svg.Reference.csproj", "{4C572A79-0878-4841-82E1-B3125B03036B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Uno.UI.RemoteControl.Messaging", "Uno.UI.RemoteControl.Messaging\Uno.UI.RemoteControl.Messaging.csproj", "{8E3C8617-ABC2-464C-9376-1B334250F80F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Uno.UI.RemoteControl.Messaging", "Uno.UI.RemoteControl.Messaging\Uno.UI.RemoteControl.Messaging.csproj", "{8E3C8617-ABC2-464C-9376-1B334250F80F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnoIslandsSamplesApp.Skia", "SamplesApp\UnoIslandsSamplesApp.Skia\UnoIslandsSamplesApp.Skia.csproj", "{FA0E451F-69EB-4E90-BC77-696B16391C02}"
EndProject
......
......@@ -32,7 +32,7 @@ namespace Windows.UI.Xaml.Markup.Reader
// Force the line info, otherwise it will be enabled only when the debugger is attached.
var settings = new XamlXmlReaderSettings() { ProvideLineInfo = true };
using (var reader = new XamlXmlReader(document, context, settings))
using (var reader = new XamlXmlReader(document, context, settings, (_, _) => IsIncludedResult.Default))
{
if (reader.Read())
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册