Example #1
0
        internal static Type GetCanonicalDotNetType(Type type)
        {
            var baseTypes = type.GetInterfaces().ToList();

            if (type.BaseType != null)
            {
                baseTypes.Add(type.BaseType);
            }

            foreach (var baseType in baseTypes)
            {
                var attr = TypeUtils.GetCustomAttributesData(baseType).FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateCanonicalDotNetTypeScriptTypeAttributeAttributeName);

                if (attr != null)
                {
                    return(baseType);
                }

                var parentCanonical = GetCanonicalDotNetType(baseType);
                if (parentCanonical != null)
                {
                    return(parentCanonical);
                }
            }

            return(null);
        }
Example #2
0
        internal static string GetTypescriptNamespace(Type type)
        {
            var parentToAugument = TypeBuilder.GetParentTypeToAugument(type);

            if (parentToAugument != null)
            {
                type = parentToAugument;
            }

            string DoGetTypescriptNamespace(object typeOrAssembly)
            {
                var customAttributes = typeOrAssembly is Type type?TypeUtils.GetCustomAttributesData(type) : TypeUtils.GetAssemblyCustomAttributesData((Assembly)typeOrAssembly);

                var attr = customAttributes.FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateTypeScriptNamespaceAttributeName && a.ConstructorArguments.Count == 1 && a.ConstructorArguments[0].Value is string);

                return((string)attr?.ConstructorArguments[0].Value);
            }

            for (var currentType = type; currentType != null; currentType = currentType.DeclaringType)
            {
                var ns = DoGetTypescriptNamespace(currentType);
                if (ns != null)
                {
                    return(ns);
                }
            }

            return(DoGetTypescriptNamespace(type.Assembly));
        }
Example #3
0
        internal static bool ShouldGenerateDotNetTypeNamesAsJsDocComment(Type type)
        {
            bool DoShouldGenerateDotNetTypeNamesAsJsDocComment(object typeOrAssembly)
            {
                var customAttributes = typeOrAssembly is Type type?TypeUtils.GetCustomAttributesData(type) : TypeUtils.GetAssemblyCustomAttributesData((Assembly)typeOrAssembly);

                var attr = customAttributes.FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateDotNetTypeNamesAsJsDocCommentAttributeName);

                return(attr != null);
            }

            if (DoShouldGenerateDotNetTypeNamesAsJsDocComment(type.Assembly))
            {
                return(true);
            }

            for (var currentType = type; currentType != null; currentType = currentType.DeclaringType)
            {
                var shouldGenerate = DoShouldGenerateDotNetTypeNamesAsJsDocComment(currentType);
                if (shouldGenerate)
                {
                    return(true);
                }
            }

            return(false);
        }
Example #4
0
        private static string GetTypeMemberName(Type type)
        {
            // No reason to create a type member on an abstract type since the purpose of the type member
            // is to identify a concrete type
            if (type.IsAbstract)
            {
                return(null);
            }

            var typeMemberName = (string)null;
            var currentType    = type;

            while (currentType != null)
            {
                var attr = TypeUtils.GetCustomAttributesData(currentType).FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateTypeScriptTypeMemberAttributeName);
                if (attr != null)
                {
                    if (attr.ConstructorArguments[0].Value is string name)
                    {
                        typeMemberName = name;
                    }
                    else
                    {
                        typeMemberName = Constants.DefaultTypeMemberName;
                    }
                    break;
                }

                currentType = currentType.BaseType;
            }

            return(typeMemberName);
        }
Example #5
0
        private static TsInterfaceMember BuildMember(MemberInfo member, IList <Type> interfaces, TypeBuilderConfig config, string currentTsNamespace)
        {
            var interfaceProperties = interfaces.SelectMany(i => TypeUtils.GetRelevantAndBaseProperties(i).Where(p => p.Name == member.Name));

            var allPropertiesToCheckForIgnore = new List <MemberInfo>();

            allPropertiesToCheckForIgnore.Add(member);
            allPropertiesToCheckForIgnore.AddRange(interfaceProperties);

            var currentType = member.DeclaringType?.BaseType;

            while (currentType != null)
            {
                var baseProperties = TypeUtils.GetRelevantAndBaseProperties(currentType).Where(p => p.Name == member.Name);
                allPropertiesToCheckForIgnore.AddRange(baseProperties);
                currentType = currentType.BaseType;
            }

            foreach (var propertyToCheckForIgnore in allPropertiesToCheckForIgnore)
            {
                var attributes = TypeUtils.GetCustomAttributesData(propertyToCheckForIgnore);
                if (attributes.All(a => a.AttributeType.Name != Constants.TypeScriptTypeAttributeName))
                {
                    if (attributes.Any(a => a.AttributeType.FullName == "Newtonsoft.Json.JsonIgnoreAttribute"))
                    {
                        return(null);
                    }

                    if (attributes.Any(a => a.AttributeType.FullName == config.CustomTypeScriptIgnoreAttributeFullName))
                    {
                        return(null);
                    }

                    if (attributes.Any(a => a.AttributeType.Name == Constants.TypeScriptIgnoreAttributeName))
                    {
                        return(null);
                    }
                }
            }

            string name = FindNameFromJsonPropertyAttribute(member);

            if (string.IsNullOrEmpty(name))
            {
                name = StringUtils.ToCamelCase(member.Name);
            }

            var membersToCheckForOptional = new List <MemberInfo> {
                member
            };

            membersToCheckForOptional.AddRange(member.DeclaringType.GetInterfaces().SelectMany(i => i.GetMember(member.Name)).Where(m => m != null));

            var isOptional = membersToCheckForOptional.SelectMany(m => TypeUtils.GetCustomAttributesData(m)).FirstOrDefault(a => a.AttributeType.Name == Constants.TypeScriptOptionalAttributeName) != null;

            return(new TsInterfaceMember(name, BuildTsTypeReferenceToPropertyType(member, config, currentTsNamespace, isOptional), member, isOptional));
        }
Example #6
0
        private static string GetDerivedTypesUnionName(Type type)
        {
            var attr = TypeUtils.GetCustomAttributesData(type).FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateTypeScriptDerivedTypesUnionAttributeName);

            if (attr == null)
            {
                return(null);
            }

            return(attr.ConstructorArguments.Count > 0 && attr.ConstructorArguments[0].Value is string unionName ? unionName : (TypeUtils.GetNameWithoutGenericArity(type) + "Types"));
        }
Example #7
0
        private static string FindNameFromJsonPropertyAttribute(MemberInfo member)
        {
            string LookupSingle(MemberInfo m)
            {
                var jsonPropertyAttribute = TypeUtils.GetCustomAttributesData(m).FirstOrDefault(a => a.AttributeType.FullName == "Newtonsoft.Json.JsonPropertyAttribute");

                if (jsonPropertyAttribute != null)
                {
                    if (jsonPropertyAttribute.NamedArguments?.Any(x => x.MemberName == "PropertyName") == true)
                    {
                        return(jsonPropertyAttribute.NamedArguments.First(x => x.MemberName == "PropertyName").TypedValue.Value as string);
                    }
                    else if (jsonPropertyAttribute.ConstructorArguments.Count > 0)
                    {
                        return(jsonPropertyAttribute.ConstructorArguments[0].Value as string);
                    }
                }
                return(null);
            }

            if (LookupSingle(member) is string result)
            {
                return(result);
            }

            foreach (var interfaceProperty in member.DeclaringType?.GetInterfaces().SelectMany(i => TypeUtils.GetRelevantAndBaseProperties(i).Where(p => p.Name == member.Name)) ?? new List <PropertyInfo>())
            {
                if (LookupSingle(interfaceProperty) is string interfaceResult)
                {
                    return(interfaceResult);
                }
            }

            var currentType = member.DeclaringType?.BaseType;

            while (currentType != null)
            {
                var baseProperties = TypeUtils.GetRelevantAndBaseProperties(currentType).Where(p => p.Name == member.Name);
                foreach (var baseProperty in baseProperties)
                {
                    if (LookupSingle(baseProperty) is string baseResult)
                    {
                        return(baseResult);
                    }
                }

                currentType = currentType.BaseType;
            }

            return(null);
        }
Example #8
0
        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);
        }
Example #9
0
        private bool ShouldTypeBeGenerated(Type type)
        {
            while (type != null)
            {
                var customAttributes = TypeUtils.GetCustomAttributesData(type);
                var gtsda            = customAttributes.FirstOrDefault(a => a.AttributeType.Name == Constants.GenerateTypeScriptDefinitionAttributeName);
                if (gtsda != null)
                {
                    return(gtsda.ConstructorArguments.Count == 0 || !(gtsda.ConstructorArguments[0].Value is bool value) || value);
                }

                if (customAttributes.Any(a => a.AttributeType.Name == Constants.GenerateTypeScriptDefinitionAttributeName) || customAttributes.Any(a => a.AttributeType.Name == Constants.GenerateTypeScriptNamespaceAttributeName))
                {
                    return(true);
                }

                type = type.DeclaringType;
            }

            return(false);
        }
Example #10
0
        private static CustomAttributeData GetTypeScriptTypeAttribute(List <CustomAttributeData> attributes)
        {
            var explicitTypeAttribute = attributes.FirstOrDefault(a => a.AttributeType?.Name == Constants.TypeScriptTypeAttributeName && a.ConstructorArguments.Count == 1);

            if (explicitTypeAttribute != null)
            {
                return(explicitTypeAttribute);
            }

            foreach (var attribute in attributes)
            {
                var attributeAttributes = TypeUtils.GetCustomAttributesData(attribute.AttributeType);

                var attributeAttribute = attributeAttributes.FirstOrDefault(a => a.AttributeType?.Name == Constants.TypeScriptTypeAttributeName && a.ConstructorArguments.Count == 1);
                if (attributeAttribute != null)
                {
                    return(attributeAttribute);
                }
            }

            return(null);
        }
Example #11
0
 private static CustomAttributeData GetTypeScriptTypeAttribute(Type type)
 {
     return(GetTypeScriptTypeAttribute(TypeUtils.GetCustomAttributesData(type)));
 }
Example #12
0
 private static CustomAttributeData GetTypeScriptTypeAttribute(MemberInfo member)
 {
     return(GetTypeScriptTypeAttribute(TypeUtils.GetCustomAttributesData(member)));
 }
Example #13
0
            public override string GetSource(string outputFilePath, Config config, GeneratorContext generatorContext)
            {
                var indent = "  ";

                var result = new StringBuilder();

                var name = Name;

                if (_parentToAugument != null)
                {
                    name = _parentToAugument.Name;
                }

                var typeScriptClassComment = generatorContext.GetTypeScriptComment(_type);

                if (typeScriptClassComment == null)
                {
                    var interfaces = _type.GetInterfaces();
                    foreach (var iface in interfaces)
                    {
                        typeScriptClassComment = generatorContext.GetTypeScriptComment(iface);
                        if (typeScriptClassComment != null)
                        {
                            break;
                        }
                    }
                }

                if (TypeBuilder.ShouldGenerateDotNetTypeNamesAsJsDocComment(_type))
                {
                    var dotNetTypeAttr = TypeUtils.GetCustomAttributesData(_type).FirstOrDefault(a =>
                                                                                                 a.AttributeType.Name == Constants.GenerateTypeScriptDotNetNameAttributeName &&
                                                                                                 a.ConstructorArguments.Count == 1
                                                                                                 );

                    var type = _type;
                    if (dotNetTypeAttr?.ConstructorArguments[0].Value is Type t)
                    {
                        type = t;
                    }

                    var canonicalType     = TypeBuilder.GetCanonicalDotNetType(type);
                    var dotNetTypeComment = $"@DotNetTypeName {TypeUtils.GetFullName(type)},{type.Assembly.GetName().Name}";

                    result.Append($"{indent}/**");

                    if (typeScriptClassComment != null)
                    {
                        result.Append(config.NewLine);
                        result.Append(FormatTypeScriptComment(typeScriptClassComment, indent, config.NewLine));
                        result.Append(config.NewLine);
                        result.Append($"{indent} *");
                        result.Append(config.NewLine);
                    }

                    if (canonicalType != null)
                    {
                        result.Append(config.NewLine);
                        result.Append($"{indent} * {dotNetTypeComment}");
                        result.Append(config.NewLine);
                        result.Append($"{indent} * @DotNetCanonicalTypeName {TypeUtils.GetFullName(canonicalType)},{canonicalType.Assembly.GetName().Name}");
                        result.Append(config.NewLine);
                        result.Append($"{indent} */");
                    }
                    else
                    {
                        result.Append($" {dotNetTypeComment} */");
                    }

                    result.Append(config.NewLine);
                }
                else
                {
                    if (typeScriptClassComment != null)
                    {
                        result.Append($"{indent}/**");
                        result.Append(config.NewLine);
                        result.Append(FormatTypeScriptComment(typeScriptClassComment, indent, config.NewLine));
                        result.Append(config.NewLine);
                        result.Append($"{indent} */");
                        result.Append(config.NewLine);
                    }
                }

                result.Append($"{indent}interface {name}");
                if (_typeParameters.Length > 0)
                {
                    result.Append("<")
                    .Append(string.Join(", ", _typeParameters))
                    .Append(">");
                }

                if (_extends.Length > 0)
                {
                    var extends = _parentToAugument != null?_extends.Where(e => !e.Equals(_parentToAugument)).ToList() : _extends.ToList();

                    if (extends.Any())
                    {
                        result.Append(" extends ").Append(extends[0].GetSource());
                        for (int i = 1; i < extends.Count; i++)
                        {
                            result.Append(", ").Append(extends[i].GetSource());
                        }
                    }
                }

                result.Append(" {");
                result.Append(config.NewLine);

                if (_typeMemberName != null)
                {
                    // TODO: Should the value here be configurable? Perhaps you want the FQN?
                    result.Append($"{indent}  {_typeMemberName}: '{name}';");
                    result.Append(config.NewLine);
                }

                var memberTypeWrapper = TypeBuilder.GetWrapperTypeForMembers(_type, config);

                foreach (var m in _members)
                {
                    var optional = "";
                    if (m.IsOptional || m.Type.IsOptional)
                    {
                        if (m.IsOptional || m.Type.IsOptional)
                        {
                            optional = "?";
                        }
                    }

                    var typeScriptMemberComment = generatorContext.GetTypeScriptComment(m.MemberInfo);
                    if (typeScriptMemberComment == null)
                    {
                        var interfaceMembers = m.MemberInfo.DeclaringType.GetInterfaces().SelectMany(i => i.GetMember(m.MemberInfo.Name)).Where(m => m != null).ToList();
                        foreach (var interfaceMember in interfaceMembers)
                        {
                            typeScriptMemberComment = generatorContext.GetTypeScriptComment(interfaceMember);
                            if (typeScriptMemberComment != null)
                            {
                                break;
                            }
                        }
                    }

                    if (typeScriptMemberComment != null)
                    {
                        result.Append($"{indent}  /**");
                        result.Append(config.NewLine);
                        result.Append(FormatTypeScriptComment(typeScriptMemberComment, indent + "  ", config.NewLine));
                        result.Append(config.NewLine);
                        result.Append($"{indent}   */");
                        result.Append(config.NewLine);
                    }
                    result.Append($"{indent}  {FixName(m.Name)}{optional}: {WrapType(m.Type.GetSource(), memberTypeWrapper)};");
                    result.Append(config.NewLine);
                }

                result.Append(indent).Append("}");
                result.Append(config.NewLine);

                if (_derivedTypesUnionGeneration?.DerivedTypeReferences.Length > 0)
                {
                    result.Append(config.NewLine);
                    result.Append($"{indent}type {_derivedTypesUnionGeneration.DerivedTypesUnionName} ={config.NewLine}{indent}  | {string.Join($"{config.NewLine}{indent}  | ", _derivedTypesUnionGeneration.DerivedTypeReferences.Select(t => t.GetSource()))};");
                    result.Append(config.NewLine);
                }

                return(result.ToString());
            }