internal static Type GetParentTypeToAugument(Type type) { var attr = TypeUtils.GetCustomAttributesData(type).FirstOrDefault(a => a.AttributeType.Name == Constants.TypeScriptAugumentParentAttributeName); if (attr != null) { var baseTypes = type.GetInterfaces().ToList(); if (type.BaseType != null && !TypeUtils.Is <object>(type.BaseType)) { baseTypes.Insert(0, type.BaseType); } return(baseTypes.FirstOrDefault()); } return(null); }
public static async Task <TsTypeDefinition> BuildTsTypeDefinitionAsync(Type type, TypeBuilderConfig config, GeneratorContext generatorContext) { var tsNamespace = GetTypescriptNamespace(type); if (type.IsEnum) { var members = Enum.GetNames(type); return(TsTypeDefinition.Enum(type.Name, members)); } else { var properties = TypeUtils.GetRelevantProperties(type); var fields = TypeUtils.GetRelevantFields(type); IList <Type> extends; if (type.IsInterface) { extends = type.GetInterfaces(); } else if (type.IsValueType || TypeUtils.Is <object>(type.BaseType)) { extends = new List <Type>(); } else { extends = new List <Type> { type.BaseType }; } foreach (var iface in type.GetInterfaces()) { // We look for default interface properties because we don't generate an extends clause for C# interfaces // but that means we loose default interface properties. If any of the types interface has default properties // we include it in the extends clause. var defaultInterfaceProperties = TypeUtils.GetRelevantProperties(iface).Where(p => p.GetGetMethod()?.IsAbstract == false); properties.AddRange(defaultInterfaceProperties); } var parentToAugument = GetParentTypeToAugument(type); var parentDefToAugument = default(TsTypeDefinition); if (parentToAugument != null) { parentDefToAugument = await BuildTsTypeDefinitionAsync(parentToAugument, config, generatorContext); } var members = new List <TsInterfaceMember>(); members.AddRange(properties.Select(m => BuildMember(m, type.GetInterfaces(), config, tsNamespace)).Where(x => x != null)); members.AddRange(fields.Select(m => BuildMember(m, type.GetInterfaces(), config, tsNamespace)).Where(x => x != null)); return(TsTypeDefinition.Interface(type, members, extends.Select(e => BuildTsTypeReference(e, config, tsNamespace, true)), type.GetTypeInfo().GenericTypeParameters.Select(TypeUtils.GetNameWithoutGenericArity), GetDerivedTypes(type, config, tsNamespace, generatorContext), parentDefToAugument, GetTypeMemberName(type))); } }
private static TsTypeReference BuildTsTypeReference(Type type, TypeBuilderConfig config, string currentTsNamespace, bool returnTheMainTypeEvenIfItHasADerivedTypesUnion) { var isOptional = false; var underlyingNullableType = GetUnderlyingNullableType(type); if (underlyingNullableType != null) { type = underlyingNullableType; isOptional = true; } if (type.IsGenericParameter) { return(TsTypeReference.Simple(type.Name, isOptional)); } var typeFullName = TypeUtils.GetFullNameWithGenericArguments(type); if (typeFullName != null && config.TypeMappings.TryGetValue(typeFullName, out var mappedType)) { return(TsTypeReference.Wrap(mappedType, isOptional)); } var typeScriptTypeAttribute = GetTypeScriptTypeAttribute(type); if (typeScriptTypeAttribute != null) { if (typeScriptTypeAttribute.ConstructorArguments[0].Value is string typeString) { return(TsTypeReference.Simple(typeString)); } else if (typeScriptTypeAttribute.ConstructorArguments[0].Value is Type replaceWithType) { type = replaceWithType; } } if ( TypeUtils.Is <byte>(type) || TypeUtils.Is <sbyte>(type) || TypeUtils.Is <int>(type) || TypeUtils.Is <uint>(type) || TypeUtils.Is <long>(type) || TypeUtils.Is <ulong>(type) || TypeUtils.Is <short>(type) || TypeUtils.Is <ushort>(type) || TypeUtils.Is <double>(type) || TypeUtils.Is <decimal>(type) || TypeUtils.Is <float>(type) ) { return(TsTypeReference.Simple("number", isOptional)); } if (TypeUtils.Is <string>(type)) { return(TsTypeReference.Simple("string", isOptional)); } if (TypeUtils.Is <bool>(type)) { return(TsTypeReference.Simple("boolean", isOptional)); } var dictionaryTypes = GetDictionaryUnderlyingTypes(type); if (dictionaryTypes != null) { return(TsTypeReference.Dictionary(BuildTsTypeReference(dictionaryTypes.Item1, config, currentTsNamespace, false), BuildTsTypeReference(dictionaryTypes.Item2, config, currentTsNamespace, false))); } var enumerableUnderlyingType = GetEnumerableUnderlyingType(type); if (enumerableUnderlyingType != null) { return(TsTypeReference.Array(BuildTsTypeReference(enumerableUnderlyingType, config, currentTsNamespace, false))); } if (typeFullName != null && (type.IsClass || type.IsInterface || type.IsValueType)) { var namespaceName = GetTypescriptNamespace(type); if (!string.IsNullOrEmpty(namespaceName)) { var derivedTypesUnionName = returnTheMainTypeEvenIfItHasADerivedTypesUnion ? null : GetDerivedTypesUnionName(type); var typeName = TypeUtils.GetNameWithoutGenericArity(type); var prefix = ""; var suffix = ""; if (type.IsEnum && config.WrapConstEnumsInTemplateStrings) { prefix = "`${"; suffix = "}`"; } var result = default(TsTypeReference); if (namespaceName == currentTsNamespace) { result = TsTypeReference.Simple(prefix + (derivedTypesUnionName ?? typeName) + suffix, isOptional); } else { result = TsTypeReference.Simple(prefix + namespaceName + "." + (derivedTypesUnionName ?? typeName) + suffix, isOptional); } if (result != null) { if (type.GenericTypeArguments.Length > 0) { var typeArgs = type.GenericTypeArguments.Select(t => BuildTsTypeReference(t, config, currentTsNamespace, false)); result = TsTypeReference.Generic(result, typeArgs); } return(result); } } } return(TsTypeReference.Simple("unknown", isOptional)); }