/// <summary> /// Finds an inherited attribute on interfaces if available. /// </summary> /// <remarks> /// Performs a breadth search to find the first attribute available for the specified property. /// </remarks> /// <param name="propertyInfo">The property information.</param> /// <returns><see cref="TsPropertyAttribute"/> or null.</returns> private static TsPropertyAttribute FindInheritedAttribute(PropertyInfo propertyInfo) { Type type = propertyInfo.DeclaringType; IReadOnlyList <Type> interfaces = type.GetInterfaces(); TsPropertyAttribute attribute = null; while (interfaces.Count != 0 && attribute == null) { foreach (Type @interface in interfaces) { PropertyInfo interfaceProperty = @interface.GetProperty( propertyInfo.Name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public); if (interfaceProperty != null) { attribute = interfaceProperty.GetCustomAttribute <TsPropertyAttribute>(true); if (attribute != null) { break; } } } if (attribute == null) { interfaces = interfaces.SelectMany(i => i.GetInterfaces()).Apply(); } } return(attribute); }
private bool HasToBeNullable(TsPropertyAttribute tp, Type propType) { var hasNullable = tp != null && tp.NilForceNullable.HasValue; if (hasNullable) { return(tp.NilForceNullable.Value); } if (Context.Global.AutoOptionalProperties) { return(propType.IsNullable()); } return(false); }
/// <summary> /// Determines if the property is read only. /// </summary> /// <param name="propertyInfo">The property information.</param> /// <param name="attribute">The attribute.</param> /// <returns><c>true</c> if the property is read only, <c>false</c> otherwise.</returns> /// <exception cref="NotSupportedException">The value ({userOptions}) specified for {nameof(TsPropertyAttribute.IsReadOnly)} on the {propertyInfo.Name}</exception> private static bool GetIsReadOnly(PropertyInfo propertyInfo, TsPropertyAttribute attribute) { TsPropertyValueOptions userOptions = attribute?.IsReadOnly ?? TsPropertyValueOptions.Auto; switch (userOptions) { case TsPropertyValueOptions.Auto: return(propertyInfo.SetMethod == null); case TsPropertyValueOptions.No: return(false); case TsPropertyValueOptions.Yes: return(true); default: throw new NotSupportedException($"The value ({userOptions}) specified for {nameof(TsPropertyAttribute.IsReadOnly)} on the {propertyInfo.Name} property is not supported."); } }
/// <summary> /// Determines if the property is optional. /// </summary> /// <param name="propertyInfo">The property information.</param> /// <param name="attribute">The attribute.</param> /// <returns><c>true</c> if the property is optional, <c>false</c> otherwise.</returns> /// <exception cref="NotSupportedException">The value ({userOptions}) specified for {nameof(TsPropertyAttribute.IsOptional)} on the {propertyInfo.Name}</exception> private static bool GetIsOptional(PropertyInfo propertyInfo, TsPropertyAttribute attribute) { TsPropertyValueOptions userOptions = attribute?.IsOptional ?? TsPropertyValueOptions.Auto; switch (userOptions) { case TsPropertyValueOptions.Auto: return(propertyInfo.PropertyType.IsClass || Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null); case TsPropertyValueOptions.No: return(false); case TsPropertyValueOptions.Yes: return(true); default: throw new NotSupportedException($"The value ({userOptions}) specified for {nameof(TsPropertyAttribute.IsOptional)} on the {propertyInfo.Name} property is not supported."); } }
/// <summary> /// Fills in initialization expression /// </summary> /// <param name="element">Class member</param> /// <param name="result">Resulting AST</param> /// <param name="resolver">Type resolver</param> /// <param name="memberType">Field/property type</param> /// <param name="attr">Attribute</param> protected virtual void FillInitialization(MemberInfo element, RtField result, TypeResolver resolver, Type memberType, TsPropertyAttribute attr) { bool exportConstant = true; if (attr != null) { exportConstant = attr.Constant; } if (element.IsStatic() && exportConstant) { if (TypeResolver.NumericTypes.Contains(memberType)) { var val = GetStaticValue(element); if (val == null) { result.InitializationExpression = "null"; } else if (TypeResolver.IntegerTypes.Contains(memberType)) { result.InitializationExpression = val.ToString(); } else { double dVal = (double)val; result.InitializationExpression = dVal.ToString(JsNumberFormat); } } if (memberType == typeof(bool)) { var val = GetStaticValue(element); if (val == null) { result.InitializationExpression = "null"; } else { result.InitializationExpression = (bool)val ? "true" : "false"; } } if (memberType == typeof(string)) { var val = GetStaticValue(element); if (val == null) { result.InitializationExpression = "null"; } else { var sv = string.Format("'{0}'", val.ToString().Replace("'", "\\'")); result.InitializationExpression = sv; } } if (memberType._IsEnum()) { var val = GetStaticValue(element); if (val == null) { result.InitializationExpression = "null"; } else { var bp = Context.Project.Blueprint(memberType, false); if (bp != null) { var tn = resolver.ResolveTypeName(memberType); var name = Enum.GetName(memberType, val); result.InitializationExpression = string.Format("{0}.{1}", tn, name); } else { var v = (int)val; result.InitializationExpression = v.ToString(); } } } } if (attr?.InitializerEvaluator != null) { var val = element.IsStatic() ? GetStaticValue(element) : null; result.InitializationExpression = attr.InitializerEvaluator(element, resolver, val); } }