Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
Merge branch '4.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
StephaneDelcroix committed Sep 2, 2019
2 parents a90f544 + 397caf4 commit 14555f7
Show file tree
Hide file tree
Showing 47 changed files with 1,293 additions and 323 deletions.
79 changes: 28 additions & 51 deletions Xamarin.Forms.Build.Tasks/ExpandMarkupsVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@ namespace Xamarin.Forms.Build.Tasks
{
class ExpandMarkupsVisitor : IXamlNodeVisitor
{
readonly IList<XmlName> skips = new List<XmlName>
readonly IList<XmlName> _skips = new List<XmlName>
{
XmlName.xKey,
XmlName.xTypeArguments,
XmlName.xFactoryMethod,
XmlName.xName,
};

public ExpandMarkupsVisitor(ILContext context)
{
Context = context;
}
public ExpandMarkupsVisitor(ILContext context) => Context = context;

ILContext Context { get; }

Expand All @@ -42,17 +39,14 @@ public void Visit(ValueNode node, INode parentNode)

public void Visit(MarkupNode markupnode, INode parentNode)
{
XmlName propertyName;
if (!TryGetProperyName(markupnode, parentNode, out propertyName))
if (!TryGetProperyName(markupnode, parentNode, out XmlName propertyName))
return;
if (skips.Contains(propertyName))
if (_skips.Contains(propertyName))
return;
if (parentNode is IElementNode && ((IElementNode)parentNode).SkipProperties.Contains (propertyName))
return;
var markupString = markupnode.MarkupString;
var node = ParseExpression(ref markupString, Context, markupnode.NamespaceResolver, markupnode) as IElementNode;
if (node != null)
{
if (ParseExpression(ref markupString, Context, markupnode.NamespaceResolver, markupnode) is IElementNode node) {
((IElementNode)parentNode).Properties[propertyName] = node;
node.Accept(new XamlNodeVisitor((n, parent) => n.Parent = parent), parentNode);
}
Expand All @@ -73,11 +67,9 @@ public void Visit(ListNode node, INode parentNode)
public static bool TryGetProperyName(INode node, INode parentNode, out XmlName name)
{
name = default(XmlName);
var parentElement = parentNode as IElementNode;
if (parentElement == null)
if (!(parentNode is IElementNode parentElement))
return false;
foreach (var kvp in parentElement.Properties)
{
foreach (var kvp in parentElement.Properties) {
if (kvp.Value != node)
continue;
name = kvp.Key;
Expand All @@ -95,9 +87,7 @@ static INode ParseExpression(ref string expression, ILContext context, IXmlNames
if (expression[expression.Length - 1] != '}')
throw new XamlParseException("Markup expression missing its closing tag", xmlLineInfo);

int len;
string match;
if (!MarkupExpressionParser.MatchMarkup(out match, expression, out len))
if (!MarkupExpressionParser.MatchMarkup(out var match, expression, out var len))
throw new XamlParseException("Error while parsing markup expression", xmlLineInfo);
expression = expression.Substring(len).TrimStart();
if (expression.Length == 0)
Expand All @@ -113,31 +103,23 @@ static INode ParseExpression(ref string expression, ILContext context, IXmlNames

class ILContextProvider
{
public ILContextProvider(ILContext context)
{
Context = context;
}
public ILContextProvider(ILContext context) => Context = context;

public ILContext Context { get; }
}

class MarkupExpansionParser : MarkupExpressionParser, IExpressionParser<INode>
{
IElementNode node;
IElementNode _node;

object IExpressionParser.Parse(string match, ref string remaining, IServiceProvider serviceProvider)
{
return Parse(match, ref remaining, serviceProvider);
}
object IExpressionParser.Parse(string match, ref string remaining, IServiceProvider serviceProvider) => Parse(match, ref remaining, serviceProvider);

public INode Parse(string match, ref string remaining, IServiceProvider serviceProvider)
{
var nsResolver = serviceProvider.GetService(typeof (IXmlNamespaceResolver)) as IXmlNamespaceResolver;
if (nsResolver == null)
if (!(serviceProvider.GetService(typeof(IXmlNamespaceResolver)) is IXmlNamespaceResolver nsResolver))
throw new ArgumentException();
IXmlLineInfo xmlLineInfo = null;
var xmlLineInfoProvider = serviceProvider.GetService(typeof (IXmlLineInfoProvider)) as IXmlLineInfoProvider;
if (xmlLineInfoProvider != null)
if (serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider xmlLineInfoProvider)
xmlLineInfo = xmlLineInfoProvider.XmlLineInfo;
var contextProvider = serviceProvider.GetService(typeof (ILContextProvider)) as ILContextProvider;

Expand All @@ -146,13 +128,11 @@ public INode Parse(string match, ref string remaining, IServiceProvider serviceP
throw new ArgumentException();

string prefix, name;
if (split.Length == 2)
{
if (split.Length == 2) {
prefix = split[0];
name = split[1];
}
else
{
else {
prefix = "";
name = split[0];
}
Expand All @@ -162,47 +142,44 @@ public INode Parse(string match, ref string remaining, IServiceProvider serviceP
throw new XamlParseException($"Undeclared xmlns prefix '{prefix}'", xmlLineInfo);
//The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix.
XmlType type;
try
{
try {
type = new XmlType(namespaceuri, name + "Extension", null);
type.GetTypeReference(contextProvider.Context.Module, null);
}
catch (XamlParseException)
{
catch (XamlParseException) {
type = new XmlType(namespaceuri, name, null);
}

if (type == null)
throw new NotSupportedException();

node = xmlLineInfo == null
_node = xmlLineInfo == null
? new ElementNode(type, "", nsResolver)
: new ElementNode(type, "", nsResolver, xmlLineInfo.LineNumber, xmlLineInfo.LinePosition);

if (remaining.StartsWith("}", StringComparison.Ordinal))
{
if (remaining.StartsWith("}", StringComparison.Ordinal)) {
remaining = remaining.Substring(1);
return node;
return _node;
}

char next;
string piece;
while ((piece = GetNextPiece(ref remaining, out next)) != null)
while ((piece = GetNextPiece(ref remaining, out var next)) != null)
HandleProperty(piece, serviceProvider, ref remaining, next != '=');

return node;
return _node;
}

protected override void SetPropertyValue(string prop, string strValue, object value, IServiceProvider serviceProvider)
{
if (value == null && strValue == null)
throw new XamlParseException($"No value found for property '{prop}' in markup expression", serviceProvider);
var nsResolver = serviceProvider.GetService(typeof(IXmlNamespaceResolver)) as IXmlNamespaceResolver;
if (prop != null)
{
var name = new XmlName(node.NamespaceURI, prop);
node.Properties[name] = value as INode ?? new ValueNode(strValue, nsResolver);
if (prop != null) {
var name = new XmlName(_node.NamespaceURI, prop);
_node.Properties[name] = value as INode ?? new ValueNode(strValue, nsResolver);
}
else //ContentProperty
node.CollectionItems.Add(value as INode ?? new ValueNode(strValue, nsResolver));
_node.CollectionItems.Add(value as INode ?? new ValueNode(strValue, nsResolver));
}
}
}
Expand Down
11 changes: 4 additions & 7 deletions Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,9 @@ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, I
{
var module = context.Body.Method.Module;
var str = (string)node.Value;

//If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this
var compiledConverterName = typeConverter?.GetCustomAttribute(module, ("Xamarin.Forms.Core", "Xamarin.Forms.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value as string;
Type compiledConverterType;
if (compiledConverterName != null && (compiledConverterType = Type.GetType (compiledConverterName)) != null) {
if (typeConverter?.GetCustomAttribute(module, ("Xamarin.Forms.Core", "Xamarin.Forms.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName && (compiledConverterType = Type.GetType (compiledConverterName)) != null) {
var compiledConverter = Activator.CreateInstance (compiledConverterType);
var converter = typeof(ICompiledTypeConverter).GetMethods ().FirstOrDefault (md => md.Name == "ConvertFromString");
IEnumerable<Instruction> instructions;
Expand All @@ -159,8 +157,7 @@ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, I
}

//If there's a [TypeConverter], use it
if (typeConverter != null)
{
if (typeConverter != null) {
var isExtendedConverter = typeConverter.ImplementsInterface(module.ImportReference(("Xamarin.Forms.Core", "Xamarin.Forms", "IExtendedTypeConverter")));
var typeConverterCtorRef = module.ImportCtorReference(typeConverter, paramCount: 0);
var convertFromInvariantStringDefinition = isExtendedConverter
Expand All @@ -172,8 +169,8 @@ public static IEnumerable<Instruction> PushConvertedValue(this ValueNode node, I
.FirstOrDefault(md => md.methodDef.Name == "ConvertFromInvariantString" && md.methodDef.Parameters.Count == 1).methodDef;
var convertFromInvariantStringReference = module.ImportReference(convertFromInvariantStringDefinition);

yield return Instruction.Create(OpCodes.Newobj, typeConverterCtorRef);
yield return Instruction.Create(OpCodes.Ldstr, node.Value as string);
yield return Create(Newobj, typeConverterCtorRef);
yield return Create(Ldstr, node.Value as string);

if (isExtendedConverter)
{
Expand Down
6 changes: 3 additions & 3 deletions Xamarin.Forms.ControlGallery.iOS/CustomRenderers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
[assembly: ExportRenderer(typeof(NativeCell), typeof(NativeiOSCellRenderer))]
[assembly: ExportRenderer(typeof(NativeListView2), typeof(NativeiOSListViewRenderer))]
[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeListViewRenderer))]
[assembly: ExportRenderer(typeof(CustomMapView), typeof(CustomIOSMapRenderer))]
[assembly: ExportRenderer(typeof(Bugzilla39987.CustomMapView), typeof(CustomIOSMapRenderer))]
[assembly: ExportRenderer(typeof(TabbedPage), typeof(TabbedPageWithCustomBarColorRenderer))]
[assembly: ExportRenderer(typeof(Bugzilla43161.AccessoryViewCell), typeof(AccessoryViewCellRenderer))]
[assembly: ExportRenderer(typeof(Bugzilla36802.AccessoryViewCell), typeof(AccessoryViewCellRenderer))]
Expand All @@ -27,11 +27,11 @@
namespace Xamarin.Forms.ControlGallery.iOS
{

public class CustomIOSMapRenderer : ViewRenderer<CustomMapView, MKMapView>
public class CustomIOSMapRenderer : ViewRenderer<Bugzilla39987.CustomMapView, MKMapView>
{
private MKMapView _mapView;

protected override void OnElementChanged(ElementChangedEventArgs<CustomMapView> e)
protected override void OnElementChanged(ElementChangedEventArgs<Bugzilla39987.CustomMapView> e)
{
base.OnElementChanged(e);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Maps;
#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
Expand All @@ -13,37 +14,68 @@ namespace Xamarin.Forms.Controls.Issues
[Issue(IssueTracker.Bugzilla, 39987, "Bug 39987 - MapView not working correctly on iOS 9.3")]
public class Bugzilla39987 : TestTabbedPage // or TestMasterDetailPage, etc ...
{
const string TabTitle = "Test";
const string TestMap = "Map";
const string Ok = "Ok";
protected override void Init()
{
Children.Add(new CustomMapPage(new CustomMapView(), "Teste 1"));
Children.Add(new CustomMapPage(new CustomMapView(), "Teste 2"));
Children.Add(new CustomMapPage(new CustomMapView(), "Teste 3"));
for (int i = 1; i <= 3; i++)
Children.Add(new CustomMapPage($"{TabTitle} {i}"));
}

}

public class CustomMapView : View
{
public CustomMapView()
protected override async void OnAppearing()
{
base.OnAppearing();
await DisplayAlert("Instructions", "Navigating for all tabs, if don't crash the test passed", Ok);
}
[Preserve(AllMembers = true)]
public class CustomMapView : View
{
public CustomMapView()
{

}

}

}
[Preserve(AllMembers = true)]
public class CustomMapPage : ContentPage
{
private CustomMapView _customMapView;

public class CustomMapPage : ContentPage
{
private CustomMapView _customMapView;
public CustomMapPage(string title)
{
var map = new Map
{
AutomationId = TestMap
};
Title = title;
Content = map;
}
public CustomMapPage(CustomMapView customMapView, string title)
{
Title = title;
_customMapView = customMapView;
_customMapView.HorizontalOptions = LayoutOptions.FillAndExpand;
_customMapView.VerticalOptions = LayoutOptions.FillAndExpand;
Content = _customMapView;
}

}


public CustomMapPage(CustomMapView customMapView, string title)
#if UITEST && __IOS__
[Test]
public void MapViewInTabbedPage()
{
Title = title;
_customMapView = customMapView;
_customMapView.HorizontalOptions = LayoutOptions.FillAndExpand;
_customMapView.VerticalOptions = LayoutOptions.FillAndExpand;
Content = _customMapView;
RunningApp.WaitForElement(Ok);
RunningApp.Tap(Ok);
for (int i = 1; i <= 3; i++)
{
RunningApp.WaitForElement(TestMap);
RunningApp.Tap($"{TabTitle} {i}");
}
}
#endif

}
}
Loading

0 comments on commit 14555f7

Please sign in to comment.