public override void VisitObjCPropertyDecl(ObjCPropertyDecl decl) { // don't process methods (or types) that are unavailable for the current platform if (!decl.IsAvailable() || !(decl.DeclContext as Decl).IsAvailable()) { return; } // does not look exposed, but part of the dump if (decl.DumpToString().IndexOf("UI_APPEARANCE_SELECTOR", StringComparison.OrdinalIgnoreCase) < 0) { return; } var getter = decl.Getter; if (getter != null) { VisitObjCMethodDecl(getter); } var setter = decl.Setter; if (setter != null) { VisitObjCMethodDecl(setter); } }
protected PropertyInfo FindProperty(ObjCPropertyDecl prop) { string getNativeSelector = prop.Getter != null ? prop.Getter.Name : null; string setNativeSelector = prop.Setter != null ? prop.Setter.Name : null; foreach (PropertyInfo p in currentType.GetProperties()) { string getManagedSelector = GetSelector(p.GetGetMethod()); string setManagedSelector = GetSelector(p.GetSetMethod()); if (getNativeSelector == getManagedSelector && setNativeSelector == setManagedSelector) { return(p); } } return(null); }
public override void VisitObjCPropertyDecl(ObjCPropertyDecl decl) { // protocol members are checked in ObjCProtocolCheck if (decl.DeclContext is ObjCProtocolDecl) { 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 nativeArgumentSemantic = decl.Attributes.ToArgumentSemantic(); var nativeMethodDefinition = decl.QualifiedName; if (qualified_properties.TryGetValue(nativeMethodDefinition, out var managedArgumentSemanticList)) { foreach (var entry in managedArgumentSemanticList) { var method = entry.Item1; var managedArgumentSemantic = entry.Item2; if (managedArgumentSemantic != nativeArgumentSemantic) { // FIXME: only Copy mistakes are reported now if (managedArgumentSemantic == Helpers.ArgumentSemantic.Copy || nativeArgumentSemantic == Helpers.ArgumentSemantic.Copy) { // FIXME: rule disactivated for now // Log.On (framework).Add ($"!incorrect-argument-semantic! Native '{nativeMethodDefinition}' is declared as ({nativeArgumentSemantic.ToUsableString ().ToLowerInvariant ()}) but mapped to 'ArgumentSemantic.{managedArgumentSemantic.ToUsableString ()}' in '{method}'"); } } } } }
public override void VisitObjCPropertyDecl(ObjCPropertyDecl decl) { if (currentInterfaceDecl == null || currentType == null) { return; } PropertyInfo managedProperty = FindProperty(decl); if (managedProperty == null) { return; } bool nativeHasGetter = decl.Getter != null; bool nativeHasSetter = decl.Setter != null; bool managedHasGetter = managedProperty.CanRead; bool managedHasSetter = managedProperty.CanWrite; CheckPropertyStatus(nativeHasGetter, managedHasGetter, managedProperty, string.Format("{0} getter on {1}", decl, currentType.Name)); CheckPropertyStatus(nativeHasSetter, managedHasSetter, managedProperty, string.Format("{0} setter on {1}", decl, currentType.Name)); }
public override void VisitObjCPropertyDecl(ObjCPropertyDecl decl) { if (currentInterfaceDecl == null || currentType == null) { return; } PropertyInfo managedProperty = FindProperty(decl); if (managedProperty == null) { return; } bool nativeHasSetter = decl.Setter != null; bool managedHasSetter = managedProperty.CanWrite; if (nativeHasSetter && managedHasSetter) { ObjCPropertySetterKind nativeSetSemantic = decl.SetterKind; // Read as int so we don't have to depend on XM assembly for type // public enum ArgumentSemantic : int { // None = -1, // Assign = 0, // Copy = 1, // Retain = 2, // Weak = 3, // Strong = Retain, // UnsafeUnretained = Assign, // } int managedSetSemantic = GetArgumentSemantic(managedProperty.GetSetMethod()); // If our data type is string or string [], we _better_ be Copy on the native side. // Since we copy to/from .NET strings, ignore these to reduce noise if (nativeSetSemantic == ObjCPropertySetterKind.Copy && (managedProperty.PropertyType == typeof(string) || managedProperty.PropertyType == typeof(string []))) { return; } switch (nativeSetSemantic) { case ObjCPropertySetterKind.Assign: if (managedSetSemantic != 0 && managedSetSemantic != -1) // None maps to Assign { ReportError(currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); } break; case ObjCPropertySetterKind.Retain: if (managedSetSemantic != 2) { ReportError(currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); } break; case ObjCPropertySetterKind.Copy: if (managedSetSemantic != 1) { ReportError(currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); } break; case ObjCPropertySetterKind.Weak: if (managedSetSemantic != 3) { ReportError(currentType.Name, managedProperty.Name, managedSetSemantic, nativeSetSemantic); } break; default: throw new InvalidOperationException(string.Format("PropertyArgumentSemanticVisitor - Unknown semantic")); } } }