Implement FormsStack and FormsQueue internally for VS 2017 Compatibility (#8403)

* FormsStack and FormsQueue for VS 2017 Compat

* - sync stable vs mac versions

* - mono version

* - gtk

* - fix mono provision

* Update Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj

* - remove uwp changes

* - add 2019 back in

* Update azure-pipelines.yml
This commit is contained in:
Shane Neuville 2019-11-18 10:10:14 -07:00 коммит произвёл GitHub
Родитель 7865f64776
Коммит 34c346c521
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
24 изменённых файлов: 1139 добавлений и 93 удалений

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

@ -209,8 +209,8 @@ namespace Xamarin.Forms.Controls.Issues
int _totalWidth = 0;
int _totalHeight = 0;
Queue<string> _buttons = new Queue<string>();
Queue<string> _result = new Queue<string>();
FormsQueue<string> _buttons = new FormsQueue<string>();
FormsQueue<string> _result = new FormsQueue<string>();
public void Tap(string button)
{

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

@ -367,9 +367,9 @@ namespace Xamarin.Forms
if ((context.Attributes & BindableContextAttributes.IsBeingSet) != 0)
{
Queue<SetValueArgs> delayQueue = context.DelayedSetters;
FormsQueue<SetValueArgs> delayQueue = context.DelayedSetters;
if (delayQueue == null)
context.DelayedSetters = delayQueue = new Queue<SetValueArgs>();
context.DelayedSetters = delayQueue = new FormsQueue<SetValueArgs>();
delayQueue.Enqueue(new SetValueArgs(property, context, value, currentlyApplying, attributes));
}
@ -378,7 +378,7 @@ namespace Xamarin.Forms
context.Attributes |= BindableContextAttributes.IsBeingSet;
SetValueActual(property, context, value, currentlyApplying, attributes, silent);
Queue<SetValueArgs> delayQueue = context.DelayedSetters;
FormsQueue<SetValueArgs> delayQueue = context.DelayedSetters;
if (delayQueue != null)
{
while (delayQueue.Count > 0)
@ -527,7 +527,7 @@ namespace Xamarin.Forms
{
public BindableContextAttributes Attributes;
public BindingBase Binding;
public Queue<SetValueArgs> DelayedSetters;
public FormsQueue<SetValueArgs> DelayedSetters;
public BindableProperty Property;
public object Value;
}

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

@ -376,7 +376,7 @@ namespace Xamarin.Forms
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<Element> Descendants()
{
var queue = new Queue<Element>(16);
var queue = new FormsQueue<Element>(16);
queue.Enqueue(this);
while (queue.Count > 0)
@ -513,7 +513,7 @@ namespace Xamarin.Forms
internal IEnumerable<Element> VisibleDescendants()
{
var queue = new Queue<Element>(16);
var queue = new FormsQueue<Element>(16);
queue.Enqueue(this);
while (queue.Count > 0)

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

@ -8,7 +8,7 @@ namespace Xamarin.Forms
internal class LockingSemaphore
{
static readonly Task Completed = Task.FromResult(true);
readonly Queue<TaskCompletionSource<bool>> _waiters = new Queue<TaskCompletionSource<bool>>();
readonly FormsQueue<TaskCompletionSource<bool>> _waiters = new FormsQueue<TaskCompletionSource<bool>>();
int _currentCount;
public LockingSemaphore(int initialCount)

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

@ -28,7 +28,7 @@ namespace Xamarin.Forms.Internals
}
public static List<Datum> Data = new List<Datum>(Capacity);
static Stack<Profile> Stack = new Stack<Profile>(Capacity);
static FormsStack<Profile> Stack = new FormsStack<Profile>(Capacity);
static int Depth = 0;
static bool Running = false;
static Stopwatch Stopwatch = new Stopwatch();

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

@ -16,7 +16,7 @@ namespace Xamarin.Forms.StyleSheets
_reader = reader;
}
readonly Queue<char> _cache = new Queue<char>();
readonly FormsQueue<char> _cache = new FormsQueue<char>();
//skip comments
//TODO unescape escaped sequences

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

@ -83,7 +83,7 @@ namespace Xamarin.Forms
// done before we attempt to make the new template.
if (oldValue != null)
{
var queue = new Queue<Element>(16);
var queue = new FormsQueue<Element>(16);
queue.Enqueue((Element)self);
while (queue.Count > 0)

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

@ -0,0 +1,514 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*=============================================================================
**
**
** Purpose: A circular-array implementation of a generic queue.
**
**
=============================================================================*/
/*
* Copied from https://raw.githubusercontent.com/dotnet/corefx/9cf92cbef7cf5fcf46a1b556f9c6250e67d421ab/src/System.Collections/src/System/Collections/Generic/Queue.cs
* Pre C# 8.0 features
* */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
namespace Xamarin.Forms
{
// A simple Queue of generic objects. Internally it is implemented as a
// circular buffer, so Enqueue can be O(n). Dequeue is O(1).
[DebuggerDisplay("Count = {Count}")]
internal sealed class FormsQueue<T> : IEnumerable<T>,
System.Collections.ICollection,
IReadOnlyCollection<T>
{
private T[] _array;
private int _head; // The index from which to dequeue if the queue isn't empty.
private int _tail; // The index at which to enqueue if the queue isn't full.
private int _size; // Number of elements.
private int _version;
bool _isReference;
private const int MinimumGrow = 4;
private const int GrowFactor = 200; // double each time
// Creates a queue with room for capacity objects. The default initial
// capacity and grow factor are used.
public FormsQueue()
{
Init();
_array = new T[0];
}
// Creates a queue with room for capacity objects. The default grow factor
// is used.
public FormsQueue(int capacity)
{
Init();
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity), capacity, "ArgumentOutOfRange_NeedNonNegNum");
_array = new T[capacity];
}
// Fills a Queue with the elements of an ICollection. Uses the enumerator
// to get each of the elements.
public FormsQueue(IEnumerable<T> collection)
{
Init();
if (collection == null)
throw new ArgumentNullException(nameof(collection));
_array = FormsEnumerableHelpers.ToArray(collection, out _size);
if (_size != _array.Length)
_tail = _size;
}
void Init()
{
#if NETSTANDARD1_0
_isReference = !typeof(T).GetTypeInfo().IsValueType;
#else
_isReference = !typeof(T).IsValueType;
#endif
}
// The original version of this is IsReferenceOrContainsReferences
// But I don't think we have to satisfy the Contains reference portion of the check
public bool IsReference()
{
return _isReference;
}
public int Count
{
get { return _size; }
}
bool ICollection.IsSynchronized
{
get { return false; }
}
object ICollection.SyncRoot => this;
// Removes all Objects from the queue.
public void Clear()
{
if (_size != 0)
{
if (IsReference())
{
if (_head < _tail)
{
Array.Clear(_array, _head, _size);
}
else
{
Array.Clear(_array, _head, _array.Length - _head);
Array.Clear(_array, 0, _tail);
}
}
_size = 0;
}
_head = 0;
_tail = 0;
_version++;
}
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (arrayIndex < 0 || arrayIndex > array.Length)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex), arrayIndex, "ArgumentOutOfRange_Index");
}
int arrayLen = array.Length;
if (arrayLen - arrayIndex < _size)
{
throw new ArgumentException("Argument_InvalidOffLen");
}
int numToCopy = _size;
if (numToCopy == 0)
return;
int firstPart = Math.Min(_array.Length - _head, numToCopy);
Array.Copy(_array, _head, array, arrayIndex, firstPart);
numToCopy -= firstPart;
if (numToCopy > 0)
{
Array.Copy(_array, 0, array, arrayIndex + _array.Length - _head, numToCopy);
}
}
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (array.Rank != 1)
{
throw new ArgumentException("Arg_RankMultiDimNotSupported", nameof(array));
}
if (array.GetLowerBound(0) != 0)
{
throw new ArgumentException("Arg_NonZeroLowerBound", nameof(array));
}
int arrayLen = array.Length;
if (index < 0 || index > arrayLen)
{
throw new ArgumentOutOfRangeException(nameof(index), index, "ArgumentOutOfRange_Index");
}
if (arrayLen - index < _size)
{
throw new ArgumentException("Argument_InvalidOffLen");
}
int numToCopy = _size;
if (numToCopy == 0)
return;
try
{
int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy;
Array.Copy(_array, _head, array, index, firstPart);
numToCopy -= firstPart;
if (numToCopy > 0)
{
Array.Copy(_array, 0, array, index + _array.Length - _head, numToCopy);
}
}
catch (ArrayTypeMismatchException)
{
throw new ArgumentException("Argument_InvalidArrayType", nameof(array));
}
}
// Adds item to the tail of the queue.
public void Enqueue(T item)
{
if (_size == _array.Length)
{
int newcapacity = (int)((long)_array.Length * (long)GrowFactor / 100);
if (newcapacity < _array.Length + MinimumGrow)
{
newcapacity = _array.Length + MinimumGrow;
}
SetCapacity(newcapacity);
}
_array[_tail] = item;
MoveNext(ref _tail);
_size++;
_version++;
}
// GetEnumerator returns an IEnumerator over this Queue. This
// Enumerator will support removing.
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
/// <internalonly/>
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
// Removes the object at the head of the queue and returns it. If the queue
// is empty, this method throws an
// InvalidOperationException.
public T Dequeue()
{
int head = _head;
T[] array = _array;
if (_size == 0)
{
ThrowForEmptyQueue();
}
T removed = array[head];
if (IsReference())
{
array[head] = default;
}
MoveNext(ref _head);
_size--;
_version++;
return removed;
}
public bool TryDequeue(out T result)
{
int head = _head;
T[] array = _array;
if (_size == 0)
{
result = default;
return false;
}
result = array[head];
if (IsReference())
{
array[head] = default;
}
MoveNext(ref _head);
_size--;
_version++;
return true;
}
// Returns the object at the head of the queue. The object remains in the
// queue. If the queue is empty, this method throws an
// InvalidOperationException.
public T Peek()
{
if (_size == 0)
{
ThrowForEmptyQueue();
}
return _array[_head];
}
public bool TryPeek(out T result)
{
if (_size == 0)
{
result = default(T);
return false;
}
result = _array[_head];
return true;
}
// Returns true if the queue contains at least one object equal to item.
// Equality is determined using EqualityComparer<T>.Default.Equals().
public bool Contains(T item)
{
if (_size == 0)
{
return false;
}
if (_head < _tail)
{
return Array.IndexOf(_array, item, _head, _size) >= 0;
}
// We've wrapped around. Check both partitions, the least recently enqueued first.
return
Array.IndexOf(_array, item, _head, _array.Length - _head) >= 0 ||
Array.IndexOf(_array, item, 0, _tail) >= 0;
}
// Iterates over the objects in the queue, returning an array of the
// objects in the Queue, or an empty array if the queue is empty.
// The order of elements in the array is first in to last in, the same
// order produced by successive calls to Dequeue.
public T[] ToArray()
{
if (_size == 0)
{
return new T[0];
}
T[] arr = new T[_size];
if (_head < _tail)
{
Array.Copy(_array, _head, arr, 0, _size);
}
else
{
Array.Copy(_array, _head, arr, 0, _array.Length - _head);
Array.Copy(_array, 0, arr, _array.Length - _head, _tail);
}
return arr;
}
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity
// must be >= _size.
private void SetCapacity(int capacity)
{
T[] newarray = new T[capacity];
if (_size > 0)
{
if (_head < _tail)
{
Array.Copy(_array, _head, newarray, 0, _size);
}
else
{
Array.Copy(_array, _head, newarray, 0, _array.Length - _head);
Array.Copy(_array, 0, newarray, _array.Length - _head, _tail);
}
}
_array = newarray;
_head = 0;
_tail = (_size == capacity) ? 0 : _size;
_version++;
}
// Increments the index wrapping it if necessary.
private void MoveNext(ref int index)
{
// It is tempting to use the remainder operator here but it is actually much slower
// than a simple comparison and a rarely taken branch.
// JIT produces better code than with ternary operator ?:
int tmp = index + 1;
if (tmp == _array.Length)
{
tmp = 0;
}
index = tmp;
}
private void ThrowForEmptyQueue()
{
Debug.Assert(_size == 0);
throw new InvalidOperationException("InvalidOperation_EmptyQueue");
}
public void TrimExcess()
{
int threshold = (int)(((double)_array.Length) * 0.9);
if (_size < threshold)
{
SetCapacity(_size);
}
}
// Implements an enumerator for a Queue. The enumerator uses the
// internal version number of the list to ensure that no modifications are
// made to the list while an enumeration is in progress.
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
public struct Enumerator : IEnumerator<T>,
System.Collections.IEnumerator
{
private readonly FormsQueue<T> _q;
private readonly int _version;
private int _index; // -1 = not started, -2 = ended/disposed
private T _currentElement;
internal Enumerator(FormsQueue<T> q)
{
_q = q;
_version = q._version;
_index = -1;
_currentElement = default(T);
}
public void Dispose()
{
_index = -2;
_currentElement = default(T);
}
public bool MoveNext()
{
if (_version != _q._version)
throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
if (_index == -2)
return false;
_index++;
if (_index == _q._size)
{
// We've run past the last element
_index = -2;
_currentElement = default(T);
return false;
}
// Cache some fields in locals to decrease code size
T[] array = _q._array;
int capacity = array.Length;
// _index represents the 0-based index into the queue, however the queue
// doesn't have to start from 0 and it may not even be stored contiguously in memory.
int arrayIndex = _q._head + _index; // this is the actual index into the queue's backing array
if (arrayIndex >= capacity)
{
// NOTE: Originally we were using the modulo operator here, however
// on Intel processors it has a very high instruction latency which
// was slowing down the loop quite a bit.
// Replacing it with simple comparison/subtraction operations sped up
// the average foreach loop by 2x.
arrayIndex -= capacity; // wrap around if needed
}
_currentElement = array[arrayIndex];
return true;
}
public T Current
{
get
{
if (_index < 0)
ThrowEnumerationNotStartedOrEnded();
return _currentElement;
}
}
private void ThrowEnumerationNotStartedOrEnded()
{
Debug.Assert(_index == -1 || _index == -2);
throw new InvalidOperationException(_index == -1 ? "InvalidOperation_EnumNotStarted" : "InvalidOperation_EnumEnded");
}
object IEnumerator.Current
{
get { return Current; }
}
void IEnumerator.Reset()
{
if (_version != _q._version)
throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
_index = -1;
_currentElement = default(T);
}
}
}
}

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

@ -0,0 +1,497 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*=============================================================================
**
**
** Purpose: An array implementation of a generic stack.
**
**
=============================================================================*/
/*
* Copied from https://raw.githubusercontent.com/dotnet/corefx/9cf92cbef7cf5fcf46a1b556f9c6250e67d421ab/src/System.Collections/src/System/Collections/Generic/Stack.cs
* Pre C# 8.0 features
* */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Xamarin.Forms
{
[DebuggerDisplay("Count = {Count}")]
internal sealed class FormsStack<T> : IEnumerable<T>,
System.Collections.ICollection,
IReadOnlyCollection<T>
{
T[] _array; // Storage for stack elements. Do not rename (binary serialization)
int _size; // Number of items in the stack. Do not rename (binary serialization)
int _version; // Used to keep enumerator in sync w/ collection. Do not rename (binary serialization)
private const int DefaultCapacity = 4;
bool _isReference;
public FormsStack()
{
_array = new T[0];
#if NETSTANDARD1_0
_isReference = !typeof(T).GetTypeInfo().IsValueType;
#else
_isReference = !typeof(T).IsValueType;
#endif
}
// Create a stack with a specific initial capacity. The initial capacity
// must be a non-negative number.
public FormsStack(int capacity)
{
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity), capacity, "ArgumentOutOfRange_NeedNonNegNum");
_array = new T[capacity];
}
// Fills a Stack with the contents of a particular collection. The items are
// pushed onto the stack in the same order they are read by the enumerator.
public FormsStack(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException(nameof(collection));
_array = FormsEnumerableHelpers.ToArray(collection, out _size);
}
public int Count
{
get { return _size; }
}
bool ICollection.IsSynchronized
{
get { return false; }
}
object ICollection.SyncRoot => this;
// Removes all Objects from the Stack.
public void Clear()
{
if (IsReference())
{
Array.Clear(_array, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
}
_size = 0;
_version++;
}
public bool Contains(T item)
{
// Compare items using the default equality comparer
// PERF: Internally Array.LastIndexOf calls
// EqualityComparer<T>.Default.LastIndexOf, which
// is specialized for different types. This
// boosts performance since instead of making a
// virtual method call each iteration of the loop,
// via EqualityComparer<T>.Default.Equals, we
// only make one virtual call to EqualityComparer.LastIndexOf.
return _size != 0 && Array.LastIndexOf(_array, item, _size - 1) != -1;
}
// Copies the stack into an array.
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (arrayIndex < 0 || arrayIndex > array.Length)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex), arrayIndex, "ArgumentOutOfRange_Index");
}
if (array.Length - arrayIndex < _size)
{
throw new ArgumentException("Argument_InvalidOffLen");
}
Debug.Assert(array != _array);
int srcIndex = 0;
int dstIndex = arrayIndex + _size;
while (srcIndex < _size)
{
array[--dstIndex] = _array[srcIndex++];
}
}
void ICollection.CopyTo(Array array, int arrayIndex)
{
if (array == null)
{
throw new ArgumentNullException(nameof(array));
}
if (array.Rank != 1)
{
throw new ArgumentException("Arg_RankMultiDimNotSupported", nameof(array));
}
if (array.GetLowerBound(0) != 0)
{
throw new ArgumentException("Arg_NonZeroLowerBound", nameof(array));
}
if (arrayIndex < 0 || arrayIndex > array.Length)
{
throw new ArgumentOutOfRangeException(nameof(arrayIndex), arrayIndex, "ArgumentOutOfRange_Index");
}
if (array.Length - arrayIndex < _size)
{
throw new ArgumentException("Argument_InvalidOffLen");
}
try
{
Array.Copy(_array, 0, array, arrayIndex, _size);
Array.Reverse(array, arrayIndex, _size);
}
catch (ArrayTypeMismatchException)
{
throw new ArgumentException("Argument_InvalidArrayType", nameof(array));
}
}
// Returns an IEnumerator for this Stack.
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
/// <internalonly/>
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}
public void TrimExcess()
{
int threshold = (int)(((double)_array.Length) * 0.9);
if (_size < threshold)
{
Array.Resize(ref _array, _size);
_version++;
}
}
// Returns the top object on the stack without removing it. If the stack
// is empty, Peek throws an InvalidOperationException.
public T Peek()
{
int size = _size - 1;
T[] array = _array;
if ((uint)size >= (uint)array.Length)
{
ThrowForEmptyStack();
}
return array[size];
}
public bool TryPeek(out T result)
{
int size = _size - 1;
T[] array = _array;
if ((uint)size >= (uint)array.Length)
{
result = default(T);
return false;
}
result = array[size];
return true;
}
// Pops an item from the top of the stack. If the stack is empty, Pop
// throws an InvalidOperationException.
public T Pop()
{
int size = _size - 1;
T[] array = _array;
// if (_size == 0) is equivalent to if (size == -1), and this case
// is covered with (uint)size, thus allowing bounds check elimination
// https://github.com/dotnet/coreclr/pull/9773
if ((uint)size >= (uint)array.Length)
{
ThrowForEmptyStack();
}
_version++;
_size = size;
T item = array[size];
if (IsReference())
{
array[size] = default(T); // Free memory quicker.
}
return item;
}
public bool TryPop(out T result)
{
int size = _size - 1;
T[] array = _array;
if ((uint)size >= (uint)array.Length)
{
result = default(T);
return false;
}
_version++;
_size = size;
result = array[size];
if (IsReference())
{
array[size] = default(T);
}
return true;
}
// Pushes an item to the top of the stack.
public void Push(T item)
{
int size = _size;
T[] array = _array;
if ((uint)size < (uint)array.Length)
{
array[size] = item;
_version++;
_size = size + 1;
}
else
{
PushWithResize(item);
}
}
// Non-inline from Stack.Push to improve its code quality as uncommon path
[MethodImpl(MethodImplOptions.NoInlining)]
private void PushWithResize(T item)
{
Array.Resize(ref _array, (_array.Length == 0) ? DefaultCapacity : 2 * _array.Length);
_array[_size] = item;
_version++;
_size++;
}
// Copies the Stack to an array, in the same order Pop would return the items.
public T[] ToArray()
{
if (_size == 0)
return new T[0];
T[] objArray = new T[_size];
int i = 0;
while (i < _size)
{
objArray[i] = _array[_size - i - 1];
i++;
}
return objArray;
}
private void ThrowForEmptyStack()
{
Debug.Assert(_size == 0);
throw new InvalidOperationException("InvalidOperation_EmptyStack");
}
// The original version of this is IsReferenceOrContainsReferences
// But I don't think we have to satisfy the Contains reference portion of the check
public bool IsReference()
{
return _isReference;
}
[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "not an expected scenario")]
public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
{
private readonly FormsStack<T> _stack;
private readonly int _version;
private int _index;
private T _currentElement;
internal Enumerator(FormsStack<T> stack)
{
_stack = stack;
_version = stack._version;
_index = -2;
_currentElement = default;
}
public void Dispose()
{
_index = -1;
}
public bool MoveNext()
{
bool retval;
if (_version != _stack._version)
throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
if (_index == -2)
{ // First call to enumerator.
_index = _stack._size - 1;
retval = (_index >= 0);
if (retval)
_currentElement = _stack._array[_index];
return retval;
}
if (_index == -1)
{ // End of enumeration.
return false;
}
retval = (--_index >= 0);
if (retval)
_currentElement = _stack._array[_index];
else
_currentElement = default;
return retval;
}
public T Current
{
get
{
if (_index < 0)
ThrowEnumerationNotStartedOrEnded();
return _currentElement;
}
}
private void ThrowEnumerationNotStartedOrEnded()
{
Debug.Assert(_index == -1 || _index == -2);
throw new InvalidOperationException(_index == -2 ? "InvalidOperation_EnumNotStarted" : "InvalidOperation_EnumEnded");
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
void IEnumerator.Reset()
{
if (_version != _stack._version)
throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
_index = -2;
_currentElement = default;
}
}
}
/// <summary>
/// Internal helper functions for working with enumerables.
/// </summary>
internal static partial class FormsEnumerableHelpers
{
/// <summary>Converts an enumerable to an array using the same logic as List{T}.</summary>
/// <param name="source">The enumerable to convert.</param>
/// <param name="length">The number of items stored in the resulting array, 0-indexed.</param>
/// <returns>
/// The resulting array. The length of the array may be greater than <paramref name="length"/>,
/// which is the actual number of elements in the array.
/// </returns>
internal static T[] ToArray<T>(IEnumerable<T> source, out int length)
{
if (source is ICollection<T> ic)
{
int count = ic.Count;
if (count != 0)
{
// Allocate an array of the desired size, then copy the elements into it. Note that this has the same
// issue regarding concurrency as other existing collections like List<T>. If the collection size
// concurrently changes between the array allocation and the CopyTo, we could end up either getting an
// exception from overrunning the array (if the size went up) or we could end up not filling as many
// items as 'count' suggests (if the size went down). This is only an issue for concurrent collections
// that implement ICollection<T>, which as of .NET 4.6 is just ConcurrentDictionary<TKey, TValue>.
T[] arr = new T[count];
ic.CopyTo(arr, 0);
length = count;
return arr;
}
}
else
{
using (var en = source.GetEnumerator())
{
if (en.MoveNext())
{
const int DefaultCapacity = 4;
T[] arr = new T[DefaultCapacity];
arr[0] = en.Current;
int count = 1;
while (en.MoveNext())
{
if (count == arr.Length)
{
// MaxArrayLength is defined in Array.MaxArrayLength and in gchelpers in CoreCLR.
// It represents the maximum number of elements that can be in an array where
// the size of the element is greater than one byte; a separate, slightly larger constant,
// is used when the size of the element is one.
const int MaxArrayLength = 0x7FEFFFFF;
// This is the same growth logic as in List<T>:
// If the array is currently empty, we make it a default size. Otherwise, we attempt to
// double the size of the array. Doubling will overflow once the size of the array reaches
// 2^30, since doubling to 2^31 is 1 larger than Int32.MaxValue. In that case, we instead
// constrain the length to be MaxArrayLength (this overflow check works because of the
// cast to uint). Because a slightly larger constant is used when T is one byte in size, we
// could then end up in a situation where arr.Length is MaxArrayLength or slightly larger, such
// that we constrain newLength to be MaxArrayLength but the needed number of elements is actually
// larger than that. For that case, we then ensure that the newLength is large enough to hold
// the desired capacity. This does mean that in the very rare case where we've grown to such a
// large size, each new element added after MaxArrayLength will end up doing a resize.
int newLength = count << 1;
if ((uint)newLength > MaxArrayLength)
{
newLength = MaxArrayLength <= count ? count + 1 : MaxArrayLength;
}
Array.Resize(ref arr, newLength);
}
arr[count++] = en.Current;
}
length = count;
return arr;
}
}
}
length = 0;
return new T[0];
}
}
}

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

@ -6,7 +6,7 @@ namespace Xamarin.Forms.Platform.Android
{
public sealed class RendererPool
{
readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, Stack<IVisualElementRenderer>>();
readonly Dictionary<Type, FormsStack<IVisualElementRenderer>> _freeRenderers = new Dictionary<Type, FormsStack<IVisualElementRenderer>>();
readonly VisualElement _oldElement;
@ -38,7 +38,7 @@ namespace Xamarin.Forms.Platform.Android
Type rendererType = Internals.Registrar.Registered.GetHandlerTypeForObject(view) ?? typeof(ViewRenderer);
Stack<IVisualElementRenderer> renderers;
FormsStack<IVisualElementRenderer> renderers;
if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
return null;
@ -82,9 +82,9 @@ namespace Xamarin.Forms.Platform.Android
var reflectableType = renderer as System.Reflection.IReflectableType;
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : renderer.GetType();
Stack<IVisualElementRenderer> renderers;
FormsStack<IVisualElementRenderer> renderers;
if (!_freeRenderers.TryGetValue(rendererType, out renderers))
_freeRenderers[rendererType] = renderers = new Stack<IVisualElementRenderer>();
_freeRenderers[rendererType] = renderers = new FormsStack<IVisualElementRenderer>();
renderers.Push(renderer);
}

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

@ -7,7 +7,7 @@ namespace Xamarin.Forms.Platform.Android
{
public class ViewPool : IDisposable
{
readonly Dictionary<Type, Stack<AView>> _freeViews = new Dictionary<Type, Stack<AView>>();
readonly Dictionary<Type, FormsStack<AView>> _freeViews = new Dictionary<Type, FormsStack<AView>>();
readonly ViewGroup _viewGroup;
bool _disposed;
@ -22,7 +22,7 @@ namespace Xamarin.Forms.Platform.Android
if (_disposed)
return;
foreach (Stack<AView> views in _freeViews.Values)
foreach (FormsStack<AView> views in _freeViews.Values)
{
foreach (AView view in views)
view.Dispose();
@ -44,7 +44,7 @@ namespace Xamarin.Forms.Platform.Android
if (_disposed)
throw new ObjectDisposedException(null);
Stack<AView> views;
FormsStack<AView> views;
if (_freeViews.TryGetValue(typeof(TView), out views) && views.Count > 0)
return (TView)views.Pop();
@ -66,9 +66,9 @@ namespace Xamarin.Forms.Platform.Android
ClearChildren(g);
Type childType = child.GetType();
Stack<AView> stack;
FormsStack<AView> stack;
if (!_freeViews.TryGetValue(childType, out stack))
_freeViews[childType] = stack = new Stack<AView>();
_freeViews[childType] = stack = new FormsStack<AView>();
stack.Push(child);
}

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

@ -58,6 +58,12 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsQueue.cs">
<Link>corefx\FormsQueue.cs</Link>
</Compile>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsStack.cs">
<Link>corefx\FormsStack.cs</Link>
</Compile>
<Compile Include="ActivityResultCallbackRegistry.cs" />
<Compile Include="AndroidApplicationLifecycleState.cs" />
<Compile Include="AndroidTitleBarVisibility.cs" />
@ -395,4 +401,4 @@
<MSBuild Targets="Restore" Projects="Xamarin.Forms.Platform.Android.csproj" Properties="CreateAllAndroidTargets=false;Configuration=$(Configuration);Platform=$(Platform);">
</MSBuild>
</Target>
</Project>
</Project>

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

@ -18,7 +18,7 @@ namespace Xamarin.Forms.Platform.GTK.Renderers
{
private const int NavigationAnimationDuration = 250; // Ms
private Stack<NavigationChildPage> _currentStack;
private FormsStack<NavigationChildPage> _currentStack;
INavigationPageController NavigationController => Element as INavigationPageController;
@ -28,7 +28,7 @@ namespace Xamarin.Forms.Platform.GTK.Renderers
public NavigationPageRenderer()
{
_currentStack = new Stack<NavigationChildPage>();
_currentStack = new FormsStack<NavigationChildPage>();
_toolbarTracker = new GtkToolbarTracker();
}
@ -486,7 +486,7 @@ namespace Xamarin.Forms.Platform.GTK.Renderers
{
if (removeFromStack)
{
var newStack = new Stack<NavigationChildPage>();
var newStack = new FormsStack<NavigationChildPage>();
foreach (var stack in _currentStack)
{
if (stack.Page != page)

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

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PropertyGroup>
<Description>GTK# Backend for Xamarin.Forms</Description>
<AssemblyName>Xamarin.Forms.Platform.GTK</AssemblyName>
</PropertyGroup>
@ -95,6 +95,12 @@
<PackageReference Include="OpenTK" Version="3.0.1" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsQueue.cs">
<Link>corefx\FormsQueue.cs</Link>
</Compile>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsStack.cs">
<Link>corefx\FormsStack.cs</Link>
</Compile>
<Compile Include="Animations\BaseAnimation.cs" />
<Compile Include="Animations\FloatAnimation.cs" />
<Compile Include="Cells\CellBase.cs" />

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

@ -17,7 +17,7 @@ namespace Xamarin.Forms.Platform.MacOS
bool _appeared;
EventTracker _events;
VisualElementTracker _tracker;
Stack<NavigationChildPageWrapper> _currentStack = new Stack<NavigationChildPageWrapper>();
FormsStack<NavigationChildPageWrapper> _currentStack = new FormsStack<NavigationChildPageWrapper>();
NavigationPage NavigationPage => Element as NavigationPage;
@ -255,7 +255,7 @@ namespace Xamarin.Forms.Platform.MacOS
var beforePageIndex = currentList.IndexOf(p => p.Page == before);
var pageWrapper = new NavigationChildPageWrapper(page);
currentList.Insert(beforePageIndex, pageWrapper);
_currentStack = new Stack<NavigationChildPageWrapper>(currentList);
_currentStack = new FormsStack<NavigationChildPageWrapper>(currentList);
var vc = CreateViewControllerForPage(page);
vc.SetElementSize(new Size(View.Bounds.Width, View.Bounds.Height));
@ -306,7 +306,7 @@ namespace Xamarin.Forms.Platform.MacOS
if (removeFromStack)
{
var newSource = _currentStack.Reverse().Where(w => w.Page != page);
_currentStack = new Stack<NavigationChildPageWrapper>(newSource);
_currentStack = new FormsStack<NavigationChildPageWrapper>(newSource);
}
}

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

@ -23,7 +23,7 @@ namespace Xamarin.Forms.Platform.MacOS
if (disposing)
{
var viewsToLookAt = new Stack<NSView>(Subviews);
var viewsToLookAt = new FormsStack<NSView>(Subviews);
while (viewsToLookAt.Count > 0)
{
var view = viewsToLookAt.Pop();

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

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PropertyGroup>
<Description>macOS Backend for Xamarin.Forms</Description>
<AssemblyName>Xamarin.Forms.Platform.macOS</AssemblyName>
</PropertyGroup>
@ -71,6 +71,12 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsQueue.cs">
<Link>corefx\FormsQueue.cs</Link>
</Compile>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsStack.cs">
<Link>corefx\FormsStack.cs</Link>
</Compile>
<Compile Include="..\Xamarin.Forms.Platform.iOS\Extensions\LabelExtensions.cs">
<Link>Extensions\LabelExtensions.cs</Link>
</Compile>
@ -264,4 +270,4 @@
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Mac\Xamarin.Mac.CSharp.targets" />
<Target Name="_VerifyBuildSignature" />
</Project>
</Project>

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

@ -115,7 +115,7 @@ namespace Xamarin.Forms.Platform.MacOS
internal static T FindDescendantView<T>(this UIView view) where T : UIView
{
var queue = new Queue<UIView>();
var queue = new FormsQueue<UIView>();
queue.Enqueue(view);
while (queue.Count > 0)

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

@ -10,8 +10,8 @@ namespace Xamarin.Forms.Platform.MacOS
{
public sealed class RendererPool
{
readonly Dictionary<Type, Stack<IVisualElementRenderer>> _freeRenderers =
new Dictionary<Type, Stack<IVisualElementRenderer>>();
readonly Dictionary<Type, FormsStack<IVisualElementRenderer>> _freeRenderers =
new Dictionary<Type, FormsStack<IVisualElementRenderer>>();
readonly VisualElement _oldElement;
@ -36,7 +36,7 @@ namespace Xamarin.Forms.Platform.MacOS
var rendererType = Internals.Registrar.Registered.GetHandlerTypeForObject(view) ?? typeof(ViewRenderer);
Stack<IVisualElementRenderer> renderers;
FormsStack<IVisualElementRenderer> renderers;
if (!_freeRenderers.TryGetValue(rendererType, out renderers) || renderers.Count == 0)
return null;
@ -127,9 +127,9 @@ namespace Xamarin.Forms.Platform.MacOS
var reflectableType = renderer as System.Reflection.IReflectableType;
var rendererType = reflectableType != null ? reflectableType.GetTypeInfo().AsType() : renderer.GetType();
Stack<IVisualElementRenderer> renderers;
FormsStack<IVisualElementRenderer> renderers;
if (!_freeRenderers.TryGetValue(rendererType, out renderers))
_freeRenderers[rendererType] = renderers = new Stack<IVisualElementRenderer>();
_freeRenderers[rendererType] = renderers = new FormsStack<IVisualElementRenderer>();
renderers.Push(renderer);
}

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

@ -36,7 +36,7 @@ namespace Xamarin.Forms.Platform.iOS
_insetTracker.Dispose();
_insetTracker = null;
var viewsToLookAt = new Stack<UIView>(Subviews);
var viewsToLookAt = new FormsStack<UIView>(Subviews);
while (viewsToLookAt.Count > 0)
{
var view = viewsToLookAt.Pop();

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

@ -107,6 +107,12 @@
<Compile Include="$(MSBuildThisFileDirectory)Renderers\WebViewRenderer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Properties\AssemblyInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CellExtensions.cs" />
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsQueue.cs">
<Link>corefx\FormsQueue.cs</Link>
</Compile>
<Compile Include="..\Xamarin.Forms.Core\corefx\FormsStack.cs">
<Link>corefx\FormsStack.cs</Link>
</Compile>
<Compile Include="CADisplayLinkTicker.cs" />
<Compile Include="CollectionView\CarouselViewRenderer.cs" />
<Compile Include="CollectionView\CollectionViewRenderer.cs" />

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

@ -76,7 +76,7 @@ namespace Xamarin.Forms.XamlcUnitTests
resolver.AddAssembly(Uri.UnescapeDataString((new UriBuilder(typeof(BindableObject).Assembly.CodeBase)).Path));
resolver.AddAssembly(Uri.UnescapeDataString((new UriBuilder(typeof(object).Assembly.CodeBase)).Path));
resolver.AddAssembly(Uri.UnescapeDataString((new UriBuilder(typeof(IList<>).Assembly.CodeBase)).Path));
resolver.AddAssembly(Uri.UnescapeDataString((new UriBuilder(typeof(Queue<>).Assembly.CodeBase)).Path));
resolver.AddAssembly(Uri.UnescapeDataString((new UriBuilder(typeof(FormsQueue<>).Assembly.CodeBase)).Path));
module = ModuleDefinition.CreateModule("foo", new ModuleParameters {
AssemblyResolver = resolver,
@ -89,7 +89,7 @@ namespace Xamarin.Forms.XamlcUnitTests
[TestCase(typeof(List<string>), typeof(BindableObject), ExpectedResult = false)]
[TestCase(typeof(List<string>), typeof(IEnumerable<string>), ExpectedResult = true)]
[TestCase(typeof(List<Button>), typeof(BindableObject), ExpectedResult = false)]
[TestCase(typeof(Queue<KeyValuePair<string, string>>), typeof(BindableObject), ExpectedResult = false)]
[TestCase(typeof(FormsQueue<KeyValuePair<string, string>>), typeof(BindableObject), ExpectedResult = false)]
[TestCase(typeof(double), typeof(double), ExpectedResult = true)]
[TestCase(typeof(object), typeof(IList<TriggerBase>), ExpectedResult = false)]
[TestCase(typeof(object), typeof(double), ExpectedResult = false)]

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

@ -21,6 +21,10 @@ variables:
value: 5.0.2
- name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE
value: true
- name: DOTNET_VERSION
value: 3.0.100
- name: winVmImage
value: XamarinForms
resources:
repositories:

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

@ -24,6 +24,7 @@ PowerShell:
#addin "nuget:?package=Cake.Android.SdkManager&version=3.0.2"
#addin "nuget:?package=Cake.Boots&version=1.0.0.291"
#addin "nuget:?package=Cake.FileHelpers&version=3.2.0"
//////////////////////////////////////////////////////////////////////
// TOOLS
//////////////////////////////////////////////////////////////////////
@ -43,35 +44,40 @@ var informationalVersion = gitVersion.InformationalVersion;
var buildVersion = gitVersion.FullBuildMetaData;
var nugetversion = Argument<string>("packageVersion", gitVersion.NuGetVersion);
var ANDROID_HOME = EnvironmentVariable ("ANDROID_HOME") ??
var ANDROID_HOME = EnvironmentVariable ("ANDROID_HOME") ??
(IsRunningOnWindows () ? "C:\\Program Files (x86)\\Android\\android-sdk\\" : "");
string monoMajorVersion = "5.14.0";
string monoPatchVersion = "177";
string monoMajorVersion = "5.18.1";
string monoPatchVersion = "28";
string monoVersion = $"{monoMajorVersion}.{monoPatchVersion}";
string monoSDK_windows = $"https://download.mono-project.com/archive/{monoMajorVersion}/windows-installer/mono-{monoVersion}-x64-0.msi";
string monoSDK_windows = "";//$"https://download.mono-project.com/archive/{monoMajorVersion}/windows-installer/mono-{monoVersion}-x64-0.msi";
string androidSDK_windows = "";//"https://aka.ms/xamarin-android-commercial-d15-9-windows";
string iOSSDK_windows = "https://download.visualstudio.microsoft.com/download/pr/71f33151-5db4-49cc-ac70-ba835a9f81e2/d256c6c50cd80ec0207783c5c7a4bc2f/xamarin.visualstudio.apple.sdk.4.12.3.83.vsix";
string iOSSDK_windows = "";//"https://download.visualstudio.microsoft.com/download/pr/71f33151-5db4-49cc-ac70-ba835a9f81e2/d256c6c50cd80ec0207783c5c7a4bc2f/xamarin.visualstudio.apple.sdk.4.12.3.83.vsix";
string macSDK_windows = "";
string androidSDK_macos = "https://aka.ms/xamarin-android-commercial-d15-9-macos";
monoMajorVersion = "6.4.0";
monoPatchVersion = "198";
monoVersion = $"{monoMajorVersion}.{monoPatchVersion}";
string androidSDK_macos = "https://aka.ms/xamarin-android-commercial-d16-3-macos";
string monoSDK_macos = $"https://download.mono-project.com/archive/{monoMajorVersion}/macos-10-universal/MonoFramework-MDK-{monoVersion}.macos10.xamarin.universal.pkg";
string iOSSDK_macos = $"https://bosstoragemirror.blob.core.windows.net/wrench/jenkins/xcode10.2/9c8d8e0a50e68d9abc8cd48fcd47a669e981fcc9/53/package/xamarin.ios-12.4.0.64.pkg";
string macSDK_macos = $"https://bosstoragemirror.blob.core.windows.net/wrench/jenkins/xcode10.2/9c8d8e0a50e68d9abc8cd48fcd47a669e981fcc9/53/package/xamarin.mac-5.4.0.64.pkg";
string iOSSDK_macos = $"https://bosstoragemirror.blob.core.windows.net/wrench/jenkins/d16-3/5e8a208b5f44c4885060d95e3c3ad68d6a5e95e8/40/package/xamarin.ios-13.2.0.42.pkg";
string macSDK_macos = $"https://bosstoragemirror.blob.core.windows.net/wrench/jenkins/d16-3/5e8a208b5f44c4885060d95e3c3ad68d6a5e95e8/40/package/xamarin.mac-6.2.0.42.pkg";
string androidSDK = IsRunningOnWindows() ? androidSDK_windows : androidSDK_macos;
string monoSDK = IsRunningOnWindows() ? monoSDK_windows : monoSDK_macos;
string iosSDK = IsRunningOnWindows() ? "" : iOSSDK_macos;
string iosSDK = IsRunningOnWindows() ? iOSSDK_windows : iOSSDK_macos;
string macSDK = IsRunningOnWindows() ? "" : macSDK_macos;
string[] androidSdkManagerInstalls = new string[0];//new [] { "platforms;android-24", "platforms;android-28"};
//////////////////////////////////////////////////////////////////////
// TASKS
//////////////////////////////////////////////////////////////////////
Task("Clean")
.Description("Deletes all the obj/bin directories")
.Does(() =>
{
CleanDirectories("./**/obj", (fsi)=> !fsi.Path.FullPath.Contains("XFCorePostProcessor") && !fsi.Path.FullPath.StartsWith("tools"));
@ -79,6 +85,7 @@ Task("Clean")
});
Task("provision-macsdk")
.Description("Install Xamarin.Mac SDK")
.Does(async () =>
{
if(!IsRunningOnWindows() && !String.IsNullOrWhiteSpace(macSDK))
@ -88,13 +95,11 @@ Task("provision-macsdk")
});
Task("provision-iossdk")
.Description("Install Xamarin.iOS SDK")
.Does(async () =>
{
if(!IsRunningOnWindows())
{
if(!String.IsNullOrWhiteSpace(iosSDK))
await Boots(iosSDK);
}
if(!String.IsNullOrWhiteSpace(iosSDK))
await Boots(iosSDK);
});
Task("provision-androidsdk")
@ -105,12 +110,12 @@ Task("provision-androidsdk")
if(androidSdkManagerInstalls.Length > 0)
{
var androidSdkSettings = new AndroidSdkManagerToolSettings {
var androidSdkSettings = new AndroidSdkManagerToolSettings {
SdkRoot = ANDROID_HOME,
SkipVersionCheck = true
};
AcceptLicenses (androidSdkSettings);
AndroidSdkManagerUpdateAll (androidSdkSettings);
@ -124,13 +129,20 @@ Task("provision-androidsdk")
});
Task("provision-monosdk")
.Description("Install Mono SDK")
.Does(async () =>
{
if(IsRunningOnWindows())
{
if(!String.IsNullOrWhiteSpace(monoSDK))
{
string monoPath = $"{System.IO.Path.GetTempPath()}/mono.msi";
string monoPath = $"{System.IO.Path.GetTempPath()}mono.msi";
if(!String.IsNullOrWhiteSpace(EnvironmentVariable("Build.Repository.LocalPath")))
monoPath = EnvironmentVariable("Build.Repository.LocalPath") + "\\" + "mono.msi";
Information("Mono Path: {0}", monoPath);
Information("Mono Version: {0}", monoSDK);
DownloadFile(monoSDK, monoPath);
StartProcess("msiexec", new ProcessSettings {
@ -145,34 +157,41 @@ Task("provision-monosdk")
else
{
if(!String.IsNullOrWhiteSpace(monoSDK))
await Boots(monoSDK);
await Boots(monoSDK);
}
});
Task("provision")
.Description("Install SDKs required to build project")
.IsDependentOn("provision-macsdk")
.IsDependentOn("provision-iossdk")
.IsDependentOn("provision-monosdk")
.IsDependentOn("provision-androidsdk");
Task("NuGetPack")
.Description("Build and Create Nugets")
.IsDependentOn("Build")
.IsDependentOn("_NuGetPack");
Task("_NuGetPack")
.Description("Create Nugets without building anything")
.Does(() =>
{
var nugetVersionFile =
GetFiles(".XamarinFormsVersionFile.txt");
var nugetversion = FileReadText(nugetVersionFile.First());
Information("Nuget Version: {0}", nugetversion);
var nugetPackageDir = Directory("./artifacts");
var nuGetPackSettings = new NuGetPackSettings
{
{
OutputDirectory = nugetPackageDir,
Version = nugetversion
};
var nugetFilePaths =
var nugetFilePaths =
GetFiles("./.nuspec/*.nuspec");
nuGetPackSettings.Properties.Add("configuration", configuration);
@ -183,6 +202,7 @@ Task("_NuGetPack")
Task("Restore")
.Description("Restore target on Xamarin.Forms.sln")
.Does(() =>
{
try{
@ -195,23 +215,12 @@ Task("Restore")
}
});
Task("BuildHack")
.IsDependentOn("Restore")
.Does(() =>
{
if(!IsRunningOnWindows())
{
MSBuild("./Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj", GetMSBuildSettings().WithRestore());
}
});
Task("Build")
.Description("Builds all necessary projects to create Nuget Packages")
.IsDependentOn("Restore")
.IsDependentOn("BuildHack")
.IsDependentOn("Android81")
.Does(() =>
{
{
try{
MSBuild("./Xamarin.Forms.sln", GetMSBuildSettings().WithRestore());
}
@ -223,10 +232,10 @@ Task("Build")
});
Task("Android81")
.IsDependentOn("BuildHack")
.Description("Builds Monodroid81 targets")
.Does(() =>
{
string[] androidProjects =
string[] androidProjects =
new []
{
"./Xamarin.Forms.Platform.Android/Xamarin.Forms.Platform.Android.csproj",
@ -236,20 +245,20 @@ Task("Android81")
};
foreach(var project in androidProjects)
MSBuild(project,
MSBuild(project,
GetMSBuildSettings()
.WithRestore()
.WithProperty("AndroidTargetFrameworkVersion", "v8.1"));
});
Task("VSMAC")
.IsDependentOn("BuildHack")
.Description("Builds projects necessary so solution compiles on VSMAC")
.Does(() =>
{
StartProcess("open", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
StartProcess("open", new ProcessSettings{ Arguments = "Xamarin.Forms.sln" });
});
/*
/*
Task("Deploy")
.IsDependentOn("DeployiOS")
.IsDependentOn("DeployAndroid");
@ -258,16 +267,16 @@ Task("Deploy")
// TODO? Not sure how to make this work
Task("DeployiOS")
.Does(() =>
{
{
// not sure how to get this to deploy to iOS
BuildiOSIpa("./Xamarin.Forms.sln", platform:"iPhoneSimulator", configuration:"Debug");
});
*/
Task("DeployAndroid")
.IsDependentOn("BuildHack")
.Description("Builds and deploy Android Control Gallery")
.Does(() =>
{
{
MSBuild("./Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj", GetMSBuildSettings().WithRestore());
MSBuild("./Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj", GetMSBuildSettings().WithRestore());
BuildAndroidApk("./Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj", sign:true, configuration:configuration);
@ -293,11 +302,9 @@ RunTarget(target);
MSBuildSettings GetMSBuildSettings()
{
var msbuildSettings = new MSBuildSettings();
msbuildSettings.PlatformTarget = PlatformTarget.MSIL;
msbuildSettings.MSBuildPlatform = (Cake.Common.Tools.MSBuild.MSBuildPlatform)1;
msbuildSettings.Configuration = configuration;
return msbuildSettings;
}
return new MSBuildSettings {
PlatformTarget = PlatformTarget.MSIL,
MSBuildPlatform = Cake.Common.Tools.MSBuild.MSBuildPlatform.x86,
Configuration = configuration,
};
}