/// <summary>
/// Gets value indicating whether specified object of type <paramref name="type"/> handles <c>[]</c> operator.
/// In case of ambiguity, all ambiguities must support the array access operator.
/// </summary>
/// <param name="type">Type of the object.</param>
/// <param name="ctx">Type context.</param>
/// <param name="model">Type provider.</param>
/// <returns>True iff <c>[]</c> operator is allowed.</returns>
internal static bool HasArrayAccess(TypeRefMask type, TypeRefContext /*!*/ ctx, ISymbolProvider /*!*/ model)
{
// quick check:
if (type.IsAnyType || type.IsVoid || type.IsRef)
{
return(false);
}
// check types with array access operator support:
foreach (var t in ctx.GetTypes(type))
{
switch (t.TypeCode)
{
case PhpTypeCode.String:
case PhpTypeCode.WritableString:
case PhpTypeCode.PhpArray:
break; // ok
case PhpTypeCode.Object:
// object implementing ArrayAccess
var symbol = (NamedTypeSymbol)model.ResolveType(t.QualifiedName);
if (symbol.IsValidType() && symbol.IsOfType((TypeSymbol)model.ResolveType(NameUtils.SpecialNames.ArrayAccess)))
{
break; // ok
}
goto default;
default:
return(false);
}
}
// passed all checks:
return(true);
}