Exemplo n.º 1
0
        static string GetCategoryBase(ObjCCategoryDecl category)
        {
            // I really dislike doing this
            switch (category.Name)
            {
            case "UIResponderStandardEditActions":
                // we inlined this protocol in UIResponder but Apple has it on NSObject
                return("UIResponder");

            case "UIAccessibility":
                // we inlined this protocol in UIView... but Apple has it on NSObject
                return("UIView");

            case "UIAccessibilityAction":
                // we inlined this protocol in UIResponder but Apple has it on NSObject
                return("UIResponder");

            default:
                return(Helpers.GetManagedName(category.ClassInterface.Name));
            }
        }
Exemplo n.º 2
0
        public override void VisitEnumDecl(EnumDecl decl, VisitKind visitKind)
        {
            if (visitKind != VisitKind.Enter)
            {
                return;
            }
            if (!decl.IsDefinition)
            {
                return;
            }

            string name = decl.Name;

            if (name == null)
            {
                return;
            }

            // check availability macros to see if the API is available on the OS and not deprecated
            if (!decl.IsAvailable())
            {
                return;
            }

            var framework = Helpers.GetFramework(decl);

            if (framework == null)
            {
                return;
            }

            var mname = Helpers.GetManagedName(name);

            if (!enums.TryGetValue(mname, out var type))
            {
                Log.On(framework).Add($"!missing-enum! {name} not bound");
                return;
            }
            else
            {
                enums.Remove(mname);
            }

            int  native_size = 4;
            bool native      = false;

            // FIXME: this can be simplified
            switch (decl.IntegerQualType.ToString())
            {
            case "NSInteger":
            case "NSUInteger":
            case "CFIndex":
            case "CFOptionFlags":
            case "AVAudioInteger":
                native_size = 8;                 // in managed code it's always the largest size
                native      = true;
                break;

            case "unsigned long":
            case "unsigned int":
            case "int32_t":
            case "uint32_t":
            case "int":
            case "GLint":
            case "GLuint":
            case "GLenum":
            case "SInt32":
            case "UInt32":
            case "OptionBits":             // UInt32
            case "long":
            case "FourCharCode":
            case "OSStatus":
                break;

            case "int64_t":
            case "uint64_t":
            case "unsigned long long":
            case "CVOptionFlags":             // uint64_t
                native_size = 8;
                break;

            case "UInt16":
            case "int16_t":
            case "uint16_t":
            case "short":
                native_size = 2;
                break;

            case "UInt8":
            case "int8_t":
            case "uint8_t":
                native_size = 1;
                break;

            default:
                throw new NotImplementedException(decl.IntegerQualType.ToString());
            }

            // check correct [Native] decoration
            if (native)
            {
                if (!IsNative(type))
                {
                    Log.On(framework).Add($"!missing-enum-native! {name}");
                }
            }
            else
            {
                if (IsNative(type))
                {
                    Log.On(framework).Add($"!extra-enum-native! {name}");
                }
            }

            int managed_size = 4;

            switch (GetEnumUnderlyingType(type).Name)
            {
            case "Byte":
            case "SByte":
                managed_size = 1;
                break;

            case "Int16":
            case "UInt16":
                managed_size = 2;
                break;

            case "Int32":
            case "UInt32":
                break;

            case "Int64":
            case "UInt64":
                managed_size = 8;
                break;

            default:
                throw new NotImplementedException();
            }
            if (native_size != managed_size)
            {
                Log.On(framework).Add($"!wrong-enum-size! {name} managed {managed_size} vs native {native_size}");
            }
        }
Exemplo n.º 3
0
        public override void VisitEnumDecl(EnumDecl decl, VisitKind visitKind)
        {
            if (visitKind != VisitKind.Enter)
            {
                return;
            }
            if (!decl.IsDefinition)
            {
                return;
            }

            string name = decl.Name;

            if (name == null)
            {
                return;
            }

            // check availability macros to see if the API is available on the OS and not deprecated
            if (!decl.IsAvailable())
            {
                return;
            }

            var framework = Helpers.GetFramework(decl);

            if (framework == null)
            {
                return;
            }

            var mname = Helpers.GetManagedName(name);

            // If our enum is obsoleted, then don't process it.
            if (obsoleted_enums.ContainsKey(mname))
            {
                return;
            }

            if (!enums.TryGetValue(mname, out var type))
            {
                Log.On(framework).Add($"!missing-enum! {name} not bound");
                return;
            }
            else
            {
                enums.Remove(mname);
            }

            int  native_size = 4;
            bool native      = false;

            // FIXME: this can be simplified
            switch (decl.IntegerQualType.ToString())
            {
            case "NSInteger":
            case "NSUInteger":
            case "CFIndex":
            case "CFOptionFlags":
            case "AVAudioInteger":
                native_size = 8;                 // in managed code it's always the largest size
                native      = true;
                break;

            case "unsigned long":
            case "unsigned int":
            case "int32_t":
            case "uint32_t":
            case "int":
            case "GLint":
            case "GLuint":
            case "GLenum":
            case "SInt32":
            case "UInt32":
            case "OptionBits":             // UInt32
            case "long":
            case "FourCharCode":
            case "OSStatus":
                break;

            case "int64_t":
            case "uint64_t":
            case "unsigned long long":
            case "CVOptionFlags":             // uint64_t
                native_size = 8;
                break;

            case "UInt16":
            case "int16_t":
            case "uint16_t":
            case "short":
                native_size = 2;
                break;

            case "UInt8":
            case "int8_t":
            case "uint8_t":
                native_size = 1;
                break;

            default:
                throw new NotImplementedException(decl.IntegerQualType.ToString());
            }

            // check correct [Native] decoration
            if (native)
            {
                if (!IsNative(type))
                {
                    Log.On(framework).Add($"!missing-enum-native! {name}");
                }
            }
            else
            {
                if (IsNative(type))
                {
                    Log.On(framework).Add($"!extra-enum-native! {name}");
                }
            }

            int  managed_size = 4;
            bool signed       = true;

            switch (GetEnumUnderlyingType(type).Name)
            {
            case "Byte":
                signed       = false;
                managed_size = 1;
                break;

            case "SByte":
                managed_size = 1;
                break;

            case "Int16":
                managed_size = 2;
                break;

            case "UInt16":
                signed       = false;
                managed_size = 2;
                break;

            case "Int32":
                break;

            case "UInt32":
                signed = false;
                break;

            case "Int64":
                managed_size = 8;
                break;

            case "UInt64":
                signed       = false;
                managed_size = 8;
                break;

            default:
                throw new NotImplementedException();
            }

            var fields = type.Fields;

            if (signed)
            {
                managed_signed_values.Clear();
                native_signed_values.Clear();
                foreach (var f in fields)
                {
                    // skip special `value__`
                    if (f.IsRuntimeSpecialName && !f.IsStatic)
                    {
                        continue;
                    }
                    if (!f.IsObsolete())
                    {
                        managed_signed_values [Convert.ToInt64(f.Constant)] = f;
                    }
                }

                long n = 0;
                foreach (var value in decl.Values)
                {
                    if ((value.InitExpr != null) && value.InitExpr.EvaluateAsInt(decl.AstContext, out var integer))
                    {
                        n = integer.SExtValue;
                    }

                    native_signed_values [n] = value.ToString();
                    // assume, sequentially assigned (in case next `value.InitExpr` is null)
                    n++;
                }

                foreach (var value in native_signed_values.Keys)
                {
                    if (!managed_signed_values.ContainsKey(value))
                    {
                        Log.On(framework).Add($"!missing-enum-value! {type.Name} native value {native_signed_values [value]} = {value} not bound");
                    }
                    else
                    {
                        managed_signed_values.Remove(value);
                    }
                }

                foreach (var value in managed_signed_values.Keys)
                {
                    if ((value == 0) && IsExtraZeroValid(type.Name, managed_signed_values [0].Name))
                    {
                        continue;
                    }
                    // value could be decorated with `[No*]` and those should not be reported
                    if (managed_signed_values [value].IsAvailable())
                    {
                        Log.On(framework).Add($"!extra-enum-value! Managed value {value} for {type.Name}.{managed_signed_values [value].Name} not found in native headers");
                    }
                }
            }
            else
            {
                managed_unsigned_values.Clear();
                native_unsigned_values.Clear();
                foreach (var f in fields)
                {
                    // skip special `value__`
                    if (f.IsRuntimeSpecialName && !f.IsStatic)
                    {
                        continue;
                    }
                    if (!f.IsObsolete())
                    {
                        managed_unsigned_values [Convert.ToUInt64(f.Constant)] = f;
                    }
                }

                ulong n = 0;
                foreach (var value in decl.Values)
                {
                    if ((value.InitExpr != null) && value.InitExpr.EvaluateAsInt(decl.AstContext, out var integer))
                    {
                        n = integer.ZExtValue;
                    }

                    native_unsigned_values [n] = value.ToString();
                    // assume, sequentially assigned (in case next `value.InitExpr` is null)
                    n++;
                }

                foreach (var value in native_unsigned_values.Keys)
                {
                    if (!managed_unsigned_values.ContainsKey(value))
                    {
                        // only for unsigned (flags) native enums we allow all bits set on 32 bits (UInt32.MaxValue)
                        // to be equal to all bit set on 64 bits (UInt64.MaxValue) since the MaxValue differs between
                        // 32bits (e.g. watchOS) and 64bits (all others) platforms
                        var log = true;
                        if (native && (value == UInt32.MaxValue))
                        {
                            log = !managed_unsigned_values.ContainsKey(UInt64.MaxValue);
                            managed_unsigned_values.Remove(UInt64.MaxValue);
                        }
                        if (log)
                        {
                            Log.On(framework).Add($"!missing-enum-value! {type.Name} native value {native_unsigned_values [value]} = {value} not bound");
                        }
                    }
                    else
                    {
                        managed_unsigned_values.Remove(value);
                    }
                }

                foreach (var value in managed_unsigned_values.Keys)
                {
                    if ((value == 0) && IsExtraZeroValid(type.Name, managed_unsigned_values [0].Name))
                    {
                        continue;
                    }
                    // value could be decorated with `[No*]` and those should not be reported
                    if (managed_unsigned_values [value].IsAvailable())
                    {
                        Log.On(framework).Add($"!extra-enum-value! Managed value {value} for {type.Name}.{managed_unsigned_values [value].Name} not found in native headers");
                    }
                }
            }

            if (native_size != managed_size)
            {
                Log.On(framework).Add($"!wrong-enum-size! {name} managed {managed_size} vs native {native_size}");
            }
        }