Exemplo n.º 1
0
        // The 'provider' parameter is only used in error messages to explain where the broken attribute comes from
        // (in particular it's not used to get the custom attributes themselves, since those may not come from this provider instance)
        static BindingImplOptions?GetBindingImplAttribute(ICustomAttributeProvider provider, IEnumerable <ICustomAttribute> attributes)
        {
            if (attributes == null)
            {
                return(null);
            }

            foreach (var ca in attributes)
            {
                TypeReference tr = ca.AttributeType;
                if (!tr.Is(Namespaces.ObjCRuntime, "BindingImplAttribute"))
                {
                    continue;
                }

                if (ca.HasFields)
                {
                    throw ErrorHelper.CreateError(2105, Errors.MT2105_A, provider.AsString());
                }
                if (ca.HasProperties)
                {
                    throw ErrorHelper.CreateError(2105, Errors.MT2105_B, provider.AsString());
                }

                switch (ca.ConstructorArguments.Count)
                {
                case 1:
                    var arg = ca.ConstructorArguments [0];
                    if (!arg.Type.Is(Namespaces.ObjCRuntime, "BindingImplOptions"))
                    {
                        throw ErrorHelper.CreateError(2105, Errors.MT2105_C, provider.AsString(), arg.Type.FullName);
                    }
                    return((BindingImplOptions)(int)arg.Value);

                default:
                    throw ErrorHelper.CreateError(2105, Errors.MT2105_D, provider.AsString(), ca.ConstructorArguments.Count);
                }
            }

            return(null);
        }
Exemplo n.º 2
0
        void ProcessAttributeProvider(ICustomAttributeProvider provider, MethodDefinition conditionA, MethodDefinition conditionB = null)
        {
            if (provider?.HasCustomAttributes != true)
            {
                return;
            }

            foreach (var ca in provider.CustomAttributes)
            {
                var tr = ca.Constructor.DeclaringType;

                if (!tr.IsPlatformType("ObjCRuntime", "BindAsAttribute"))
                {
                    continue;
                }

                if (ca.ConstructorArguments.Count != 1)
                {
                    ErrorHelper.Show(ErrorHelper.CreateWarning(LinkContext.Target.App, 4124, provider, Errors.MT4124_E, provider.AsString(), ca.ConstructorArguments.Count));
                    continue;
                }

                var managedType     = ca.ConstructorArguments [0].Value as TypeReference;
                var managedEnumType = managedType?.GetElementType().Resolve();
                if (managedEnumType == null)
                {
                    ErrorHelper.Show(ErrorHelper.CreateWarning(LinkContext.Target.App, 4124, provider, Errors.MT4124_H, provider.AsString(), managedType?.FullName));
                    continue;
                }

                // We only care about enums, BindAs attributes can be used for other types too.
                if (!managedEnumType.IsEnum)
                {
                    continue;
                }

                Tuple <MethodDefinition, MethodDefinition> pair;
                if (cache != null && cache.TryGetValue(managedEnumType, out pair))
                {
                    Preserve(pair, conditionA, conditionB);
                    continue;
                }

                // Find the Extension type
                TypeDefinition extensionType = null;
                var            extensionName = managedEnumType.Name + "Extensions";
                foreach (var type in managedEnumType.Module.Types)
                {
                    if (type.Namespace != managedEnumType.Namespace)
                    {
                        continue;
                    }
                    if (type.Name != extensionName)
                    {
                        continue;
                    }
                    extensionType = type;
                    break;
                }
                if (extensionType == null)
                {
                    Driver.Log(1, $"Could not find a smart extension type for the enum {managedEnumType.FullName} (due to BindAs attribute on {provider.AsString ()}): most likely this is because the enum isn't a smart enum.");
                    continue;
                }

                // Find the GetConstant/GetValue methods
                MethodDefinition getConstant = null;
                MethodDefinition getValue    = null;

                foreach (var method in extensionType.Methods)
                {
                    if (!method.IsStatic)
                    {
                        continue;
                    }
                    if (!method.HasParameters || method.Parameters.Count != 1)
                    {
                        continue;
                    }
                    if (method.Name == "GetConstant")
                    {
                        if (!method.ReturnType.IsPlatformType("Foundation", "NSString"))
                        {
                            continue;
                        }
                        if (method.Parameters [0].ParameterType != managedEnumType)
                        {
                            continue;
                        }
                        getConstant = method;
                    }
                    else if (method.Name == "GetValue")
                    {
                        if (!method.Parameters [0].ParameterType.IsPlatformType("Foundation", "NSString"))
                        {
                            continue;
                        }
                        if (method.ReturnType != managedEnumType)
                        {
                            continue;
                        }
                        getValue = method;
                    }
                }

                if (getConstant == null)
                {
                    Driver.Log(1, $"Could not find the GetConstant method on the supposedly smart extension type {extensionType.FullName} for the enum {managedEnumType.FullName} (due to BindAs attribute on {provider.AsString ()}): most likely this is because the enum isn't a smart enum.");
                    continue;
                }

                if (getValue == null)
                {
                    Driver.Log(1, $"Could not find the GetValue method on the supposedly smart extension type {extensionType.FullName} for the enum {managedEnumType.FullName} (due to BindAs attribute on {provider.AsString ()}): most likely this is because the enum isn't a smart enum.");
                    continue;
                }

                pair = new Tuple <MethodDefinition, MethodDefinition> (getConstant, getValue);
                if (cache == null)
                {
                    cache = new Dictionary <TypeDefinition, Tuple <MethodDefinition, MethodDefinition> > ();
                }
                cache.Add(managedEnumType, pair);
                Preserve(pair, conditionA, conditionB);
            }
        }
Exemplo n.º 3
0
        // The 'provider' parameter is only used in error messages to explain where the broken attribute comes from
        // (in particular it's not used to get the custom attributes themselves, since those may not come from this provider instance)
        static BindingImplOptions?GetBindingImplAttribute(ICustomAttributeProvider provider, IEnumerable <ICustomAttribute> attributes)
        {
            if (attributes == null)
            {
                return(null);
            }

            foreach (var ca in attributes)
            {
                TypeReference tr = ca.AttributeType;
                if (!tr.Is(Namespaces.ObjCRuntime, "BindingImplAttribute"))
                {
                    continue;
                }

                if (ca.HasFields)
                {
                    throw ErrorHelper.CreateError(2105, "The [BindingImpl] attribute on the member '{0}' is invalid: did not expect fields.", provider.AsString());
                }
                if (ca.HasProperties)
                {
                    throw ErrorHelper.CreateError(2105, "The [BindingImpl] attribute on the member '{0}' is invalid: did not expect properties.", provider.AsString());
                }

                switch (ca.ConstructorArguments.Count)
                {
                case 1:
                    var arg = ca.ConstructorArguments [0];
                    if (!arg.Type.Is(Namespaces.ObjCRuntime, "BindingImplOptions"))
                    {
                        throw ErrorHelper.CreateError(2105, "The [BindingImpl] attribute on the member '{0}' is invalid: did not expect a constructor with a '{1}' parameter type (expected 'ObjCRuntime.BindingImplOptions).", provider.AsString(), arg.Type.FullName);
                    }
                    return((BindingImplOptions)(int)arg.Value);

                default:
                    throw ErrorHelper.CreateError(2105, "The [BindingImpl] attribute on the member '{0}' is invalid: did not expect a constructor with a {1} parameters (expected 1 parameters).", provider.AsString(), ca.ConstructorArguments.Count);
                }
            }

            return(null);
        }