Ejemplo n.º 1
0
        /// <summary>
        /// Mostly used in ParametersRefBuilder.
        /// </summary>
        /// <param name="propertySchema"></param>
        /// <param name="actionName"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        /// <remarks>This shares similar navigation of schema like those in AddProperty().</remarks>
        public CodeTypeReference PropertySchemaToCodeTypeReference(OpenApiSchema propertySchema, string actionName, string propertyName)
        {
            string schemaType      = propertySchema.Type;
            bool   isPrimitiveType = TypeRefHelper.IsPrimitiveTypeOfOA(schemaType);

            if (String.IsNullOrEmpty(schemaType))
            {
                if (propertySchema.Reference != null)
                {
                    string propertyTypeNs     = NameFunc.GetNamespaceOfClassName(propertySchema.Reference.Id);
                    string propertyTypeName   = NameFunc.RefineTypeName(propertySchema.Reference.Id, propertyTypeNs);
                    string propertyTypeWithNs = NameFunc.CombineNamespaceWithClassName(propertyTypeNs, propertyTypeName);
                    return(ComponentsHelper.TranslateTypeNameToClientTypeReference(propertyTypeWithNs));
                }
                else
                {
                    if (propertySchema.Enum.Count > 0)                     //for casual enum
                    {
                        var r = GenerateCasualEnum(propertySchema, actionName, propertyName, null);
                        return(r.Item1);
                    }
                    else
                    {
                        Tuple <CodeTypeReference, bool> r = CreateCodeTypeReferenceSchemaOf(propertySchema, actionName, propertyName);
                        return(r.Item1);
                    }
                }
            }
            else
            {
                if (schemaType == "array")                 // for array
                {
                    var r = CreateArrayCodeTypeReference(propertySchema, actionName, propertyName, null, null);
                    return(r.Item1);
                }
                else if (propertySchema.Enum.Count == 0 && propertySchema.Reference != null && !isPrimitiveType)                 // for complex type
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    return(complexCodeTypeReference);
                }
                else if (propertySchema.Reference == null && propertySchema.Properties != null && propertySchema.Properties.Count > 0)                 // for casual type
                {
                    string casualTypeName = actionName + NameFunc.RefinePropertyName(propertyName);
                    var    found          = FindTypeDeclarationInNamespaces(casualTypeName, null);         //It could happenen when generating sync and async functions in C#
                    if (found == null)
                    {
                        CodeTypeDeclaration casualTypeDeclaration = AddTypeToClassNamespace(casualTypeName, null);                        //stay with the namespace of the host class
                        AddProperties(casualTypeDeclaration, propertySchema, casualTypeName, null);
                    }

                    return(TypeRefHelper.TranslateToClientTypeReference(casualTypeName));
                }
                else if (schemaType == "object" && propertySchema.AdditionalProperties != null)                 // for dictionary
                {
                    CodeTypeReference dicKeyTypeRef   = TypeRefHelper.TranslateToClientTypeReference(typeof(string));
                    CodeTypeReference dicValueTypeRef = PropertySchemaToCodeTypeReference(propertySchema.AdditionalProperties, actionName, propertyName);
                    return(new CodeTypeReference(typeof(Dictionary <,>).FullName, dicKeyTypeRef, dicValueTypeRef)); //for client codes, Dictionary is better than IDictionary, no worry of different implementation of IDictionary
                }
                else if (propertySchema.Enum.Count == 0)                                                            // for primitive type
                {
                    Type t = TypeRefHelper.PrimitiveSwaggerTypeToClrType(schemaType, propertySchema.Format);
                    return(new CodeTypeReference(t));
                }
                else if (propertySchema.Enum.Count > 0 && schemaType == "string")                 // for enum
                {
                    string[] enumMemberNames;
                    try
                    {
                        enumMemberNames = (String.IsNullOrEmpty(propertySchema.Type) || propertySchema.Type == "string")
                                                        ? propertySchema.Enum.Cast <OpenApiString>().Select(m => m.Value).ToArray()
                                                        : propertySchema.Enum.Cast <OpenApiInteger>().Select(m => "_" + m.Value.ToString()).ToArray();
                    }
                    catch (InvalidCastException ex)
                    {
                        throw new CodeGenException($"When dealing with {propertyName} of {schemaType}, error: {ex.Message}");
                    }

                    CodeTypeDeclaration existingDeclaration = FindEnumDeclaration(enumMemberNames);
                    if (existingDeclaration != null)
                    {
                        string            existingTypeName = existingDeclaration.Name;
                        CodeTypeReference enumReference    = TypeRefHelper.TranslateToClientTypeReference(existingTypeName);
                        return(enumReference);
                    }
                    else
                    {
                        var r = GenerateCasualEnum(propertySchema, actionName, propertyName, null);
                        return(r.Item1);
                    }
                }
                else if (schemaType != "string" && TypeAliasDic.TryGet(schemaType, out string aliasTypeName))                 //check TypeAliasDic
                {
                    return(new CodeTypeReference(aliasTypeName));
                }
                else if (propertySchema.Reference != null)
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    return(complexCodeTypeReference);
                }
                else                 // for casual enum
                {
                    var r = GenerateCasualEnum(propertySchema, actionName, propertyName, null);
                    return(r.Item1);
                }
            }
        }
Ejemplo n.º 2
0
        protected override void AddProperty(KeyValuePair <string, OpenApiSchema> p, CodeTypeDeclaration typeDeclaration, OpenApiSchema schema, string currentTypeName, string ns)
        {
            string propertyName = NameFunc.RefineTsPropertyName(p.Key);

            if (propertyName == currentTypeName)
            {
                Trace.TraceWarning($"Property {propertyName} found with the same name of type {currentTypeName}, and it is renamed to {propertyName}1.");
                propertyName += "1";
            }

            if (!Char.IsLetter(propertyName[0]) && propertyName[0] != '_')
            {
                propertyName = "_" + propertyName;
            }

            OpenApiSchema   propertySchema        = p.Value;
            string          primitivePropertyType = propertySchema.Type;
            bool            isPrimitiveType       = TypeRefHelper.IsPrimitiveTypeOfOA(primitivePropertyType);
            bool            isRequired            = schema.Required.Contains(p.Key); //compare with the original key
            CodeMemberField clientProperty;

            if (String.IsNullOrEmpty(primitivePropertyType))
            {
                if (propertySchema.Reference != null)
                {
                    string            propertyTypeNs     = NameFunc.GetNamespaceOfClassName(propertySchema.Reference.Id);
                    string            propertyTypeName   = NameFunc.RefineTypeName(propertySchema.Reference.Id, propertyTypeNs);
                    string            propertyTypeWithNs = NameFunc.CombineNamespaceWithClassName(propertyTypeNs, propertyTypeName);
                    CodeTypeReference ctr = ComponentsHelper.TranslateTypeNameToClientTypeReference(propertyTypeWithNs);
                    clientProperty = CreateProperty(ctr, propertyName, isRequired);                     //TS
                }
                else
                {
                    if (propertySchema.Enum.Count > 0)                     //for casual enum
                    {
                        clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, isRequired);
                    }
                    else
                    {
                        var r = CreateCodeTypeReferenceSchemaOf(propertySchema, currentTypeName, p.Key);
                        clientProperty = CreateProperty(r.Item1, propertyName, isRequired);
                    }
                }
            }
            else
            {
                if (propertySchema.Type == "array")                 // for array
                {
                    var r = CreateArrayCodeTypeReference(propertySchema, typeDeclaration.Name, propertyName, currentTypeName, ns);
                    CodeTypeReference arrayCodeTypeReference = r.Item1;
                    var n = String.IsNullOrEmpty(r.Item2) ? propertyName : r.Item2;
                    clientProperty = CreateProperty(arrayCodeTypeReference, n, isRequired);
                }
                else if (propertySchema.Enum.Count == 0 && propertySchema.Reference != null && !isPrimitiveType)                 // for complex type
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    clientProperty = CreateProperty(complexCodeTypeReference, propertyName, isRequired);
                }
                else if (propertySchema.Reference == null && propertySchema.Properties != null && propertySchema.Properties.Count > 0)                 // for casual type
                {
                    string casualTypeName = currentTypeName + NameFunc.RefinePropertyName(propertyName);
                    CodeTypeDeclaration casualTypeDeclaration = AddTypeToClassNamespace(casualTypeName, null);                    //stay with the namespace of the host class
                    AddProperties(casualTypeDeclaration, propertySchema, casualTypeName, null);
                    var ctr = TypeRefHelper.TranslateToClientTypeReference(casualTypeName);
                    clientProperty = CreateProperty(ctr, propertyName, isRequired);
                }
                else if (propertySchema.Type == "object" && propertySchema.AdditionalProperties != null)                 // for dictionary
                {
                    CodeTypeReference dicKeyTypeRef = TypeRefHelper.TranslateToClientTypeReference(typeof(string));
                    CodeTypeReference dicValueTypeRef;
                    if (propertySchema.AdditionalProperties.Properties.Count == 0 &&                  //not casual type
                        propertySchema.AdditionalProperties.Reference == null &&                         // not complex type
                        propertySchema.AdditionalProperties.Items == null)                            // not casual array type
                    {
                        dicValueTypeRef = new CodeTypeReference(typeof(object));
                    }
                    else
                    {
                        dicValueTypeRef = PropertySchemaToCodeTypeReference(propertySchema.AdditionalProperties, typeDeclaration.Name, propertyName);
                    }

                    CodeTypeReference dicCtr = new CodeTypeReference(typeof(Dictionary <,>).FullName, dicKeyTypeRef, dicValueTypeRef);                    //for client codes, Dictionary is better than IDictionary, no worry of different implementation of IDictionary
                    clientProperty = CreateProperty(dicCtr, propertyName, isRequired);
                }
                else if (propertySchema.Enum.Count == 0)                 // for primitive type
                {
                    Type simpleType = TypeRefHelper.PrimitiveSwaggerTypeToClrType(primitivePropertyType, propertySchema.Format);
                    clientProperty = CreatePropertyOfType(propertyName, simpleType, isRequired);
                }
                else if (propertySchema.Enum.Count > 0 && propertySchema.Type == "string")                 // for enum
                {
                    string[] enumMemberNames;
                    try
                    {
                        enumMemberNames = (String.IsNullOrEmpty(propertySchema.Type) || propertySchema.Type == "string")
                                                        ? propertySchema.Enum.Cast <OpenApiString>().Select(m => m.Value).ToArray()
                                                        : propertySchema.Enum.Cast <OpenApiInteger>().Select(m => "_" + m.Value.ToString()).ToArray();
                    }
                    catch (InvalidCastException ex)
                    {
                        throw new CodeGenException($"When dealing with {propertyName} of {propertySchema.Type}, error: {ex.Message}");
                    }

                    CodeTypeDeclaration existingDeclaration = FindEnumDeclaration(enumMemberNames);
                    if (existingDeclaration != null)
                    {
                        string            existingTypeName = existingDeclaration.Name;
                        CodeTypeReference enumReference    = TypeRefHelper.TranslateToClientTypeReference(existingTypeName);
                        clientProperty = CreateProperty(enumReference, propertyName, isRequired);
                    }
                    else
                    {
                        clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, isRequired);
                    }
                }
                else if (propertySchema.Type != "string" && TypeAliasDic.TryGet(propertySchema.Type, out string aliasTypeName))                 //check TypeAliasDic
                {
                    var r = new CodeTypeReference(aliasTypeName);
                    clientProperty = CreateProperty(r, propertyName, isRequired);
                }
                else if (propertySchema.Reference != null)
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    clientProperty = CreateProperty(complexCodeTypeReference, propertyName, isRequired);
                }
                else                 // for casual enum
                {
                    clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, isRequired);
                }
            }

            CreateMemberDocComment(p, clientProperty);
            typeDeclaration.Members.Add(clientProperty);
        }
        protected override void AddProperty(KeyValuePair <string, OpenApiSchema> p, CodeTypeDeclaration typeDeclaration, OpenApiSchema schema, string currentTypeName, string ns)
        {
            string propertyName = NameFunc.RefinePropertyName(p.Key);

            if (propertyName == currentTypeName)
            {
                Trace.TraceWarning($"Property {propertyName} found with the same name of type {currentTypeName}, and it is renamed to {propertyName}1.");
                propertyName += "1";
            }

            if (!Char.IsLetter(propertyName[0]) && propertyName[0] != '_')
            {
                propertyName = "_" + propertyName;
            }

            bool propertyNameAdjusted = propertyName != p.Key;

            OpenApiSchema   propertySchema        = p.Value;
            string          primitivePropertyType = propertySchema.Type;
            bool            isPrimitiveType       = TypeRefHelper.IsPrimitiveTypeOfOA(primitivePropertyType);
            bool            isRequired            = schema.Required.Contains(p.Key); //compare with the original key
            string          defaultValue          = GetDefaultValue(propertySchema);
            CodeMemberField clientProperty;

            if (String.IsNullOrEmpty(primitivePropertyType))
            {
                if (propertySchema.Reference != null)
                {
                    string            propertyTypeNs     = NameFunc.GetNamespaceOfClassName(propertySchema.Reference.Id);
                    string            propertyTypeName   = NameFunc.RefineTypeName(propertySchema.Reference.Id, propertyTypeNs);
                    string            propertyTypeWithNs = NameFunc.CombineNamespaceWithClassName(propertyTypeNs, propertyTypeName);
                    CodeTypeReference ctr = ComponentsHelper.TranslateTypeNameToClientTypeReference(propertyTypeWithNs);
                    clientProperty = CreateProperty(ctr, propertyName, defaultValue);                     //C#
                }
                else
                {
                    if (propertySchema.Enum.Count > 0)                     //for casual enum
                    {
                        clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, defaultValue, !isRequired || propertySchema.Nullable);
                    }
                    else
                    {
                        Tuple <CodeTypeReference, bool> r = CreateCodeTypeReferenceSchemaOf(propertySchema, currentTypeName, p.Key);
                        bool isClass = r.Item2;
                        if ((!settings.DisableSystemNullableByDefault && !isRequired || propertySchema.Nullable) && !isClass)                         //C#.
                        //if (!settings.DisableSystemNullableByDefault && !isClass && !isRequired || propertySchema.Nullable) //C#
                        {
                            clientProperty = CreateNullableProperty(r.Item1, propertyName);
                        }
                        else if (isClass && propertySchema.Nullable && settings.UseNullableReferenceType)                         //vimeo yaml declares a reference type as nullable.
                        {
                            clientProperty = CreateNullableProperty(r.Item1, propertyName);
                        }
                        else
                        {
                            clientProperty = CreateProperty(r.Item1, propertyName, defaultValue);
                        }
                    }
                }
            }
            else
            {
                if (propertySchema.Type == "array")                 // for array
                {
                    Tuple <CodeTypeReference, string> r      = CreateArrayCodeTypeReference(propertySchema, typeDeclaration.Name, propertyName, currentTypeName, ns);
                    CodeTypeReference arrayCodeTypeReference = r.Item1;
                    string            n = String.IsNullOrEmpty(r.Item2) ? propertyName : r.Item2;
                    clientProperty = CreateProperty(arrayCodeTypeReference, n, defaultValue);
                }
                else if (propertySchema.Enum.Count == 0 && propertySchema.Reference != null && !isPrimitiveType)                 // for complex type
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    clientProperty = CreateProperty(complexCodeTypeReference, propertyName, defaultValue);
                }
                else if (propertySchema.Reference == null && propertySchema.Properties != null && propertySchema.Properties.Count > 0)                 // for casual type
                {
                    string casualTypeName     = currentTypeName + NameFunc.RefinePropertyName(propertyName);
                    CodeTypeDeclaration found = FindTypeDeclarationInNamespaces(casualTypeName, null);                     //It could happenen when generating sync and async functions in C#
                    if (found == null)
                    {
                        CodeTypeDeclaration casualTypeDeclaration = AddTypeToClassNamespace(casualTypeName, null);                        //stay with the namespace of the host class
                        AddProperties(casualTypeDeclaration, propertySchema, casualTypeName, null);
                    }

                    CodeTypeReference ctr = TypeRefHelper.TranslateToClientTypeReference(casualTypeName);
                    clientProperty = CreateProperty(ctr, propertyName, defaultValue);
                }
                else if (propertySchema.Type == "object" && propertySchema.AdditionalProperties != null)                 // for dictionary
                {
                    CodeTypeReference dicKeyTypeRef = TypeRefHelper.TranslateToClientTypeReference(typeof(string));
                    CodeTypeReference dicValueTypeRef;
                    if (propertySchema.AdditionalProperties.Properties.Count == 0 &&                  //not casual type
                        propertySchema.AdditionalProperties.Reference == null &&                         // not complex type
                        propertySchema.AdditionalProperties.Items == null)                            // not casual array type
                    {
                        dicValueTypeRef = new CodeTypeReference(typeof(object));
                    }
                    else
                    {
                        dicValueTypeRef = PropertySchemaToCodeTypeReference(propertySchema.AdditionalProperties, typeDeclaration.Name, propertyName);
                    }

                    CodeTypeReference dicCtr = new CodeTypeReference(typeof(Dictionary <,>).FullName, dicKeyTypeRef, dicValueTypeRef);                    //for client codes, Dictionary is better than IDictionary, no worry of different implementation of IDictionary
                    clientProperty = CreateProperty(dicCtr, propertyName, null);
                }
                else if (propertySchema.Enum.Count == 0)                 // for primitive type
                {
                    Type simpleType = TypeRefHelper.PrimitiveSwaggerTypeToClrType(primitivePropertyType, propertySchema.Format);
                    if ((!settings.DisableSystemNullableByDefault && !isRequired || propertySchema.Nullable) && !simpleType.IsClass)                     //C#
                    {
                        clientProperty = CreateNullableProperty(propertyName, simpleType, settings, propertySchema.Nullable);
                    }
                    else if (propertySchema.Nullable && simpleType.IsClass && settings.UseNullableReferenceType)
                    {
                        clientProperty = CreateNullableProperty(propertyName, simpleType, settings, propertySchema.Nullable);
                    }
                    else
                    {
                        clientProperty = CreateProperty(propertyName, simpleType, defaultValue);
                    }
                }
                else if (propertySchema.Enum.Count > 0 && propertySchema.Type == "string")                 // for enum
                {
                    string[] enumMemberNames;
                    try
                    {
                        enumMemberNames = (String.IsNullOrEmpty(propertySchema.Type) || propertySchema.Type == "string")
                                                        ? propertySchema.Enum.Cast <OpenApiString>().Select(m => m.Value).ToArray()
                                                        : propertySchema.Enum.Cast <OpenApiInteger>().Select(m => "_" + m.Value.ToString()).ToArray();
                    }
                    catch (InvalidCastException ex)
                    {
                        throw new CodeGenException($"When dealing with {propertyName} of {propertySchema.Type}, error: {ex.Message}");
                    }

                    CodeTypeDeclaration existingDeclaration = FindEnumDeclaration(enumMemberNames);
                    if (existingDeclaration != null)
                    {
                        string            existingTypeName = existingDeclaration.Name;
                        CodeTypeReference enumReference    = TypeRefHelper.TranslateToClientTypeReference(existingTypeName);
                        clientProperty = CreateProperty(enumReference, propertyName, String.IsNullOrEmpty(defaultValue) ? null : enumReference.BaseType + "." + defaultValue);
                    }
                    else
                    {
                        clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, defaultValue, !isRequired || propertySchema.Nullable);
                    }
                }
                else if (propertySchema.Type != "string" && TypeAliasDic.TryGet(propertySchema.Type, out string aliasTypeName))                 //check TypeAliasDic
                {
                    CodeTypeReference r = new CodeTypeReference(aliasTypeName);
                    clientProperty = CreateProperty(r, propertyName, defaultValue);
                }
                else if (propertySchema.Reference != null)
                {
                    CodeTypeReference complexCodeTypeReference = CreateComplexCodeTypeReference(propertySchema);
                    clientProperty = CreateProperty(complexCodeTypeReference, propertyName, String.IsNullOrEmpty(defaultValue) ? null : complexCodeTypeReference.BaseType + "." + defaultValue);
                }
                else                 // for casual enum
                {
                    clientProperty = GenerateCasualEnumForProperty(propertySchema, typeDeclaration.Name, propertyName, ns, defaultValue, !isRequired || propertySchema.Nullable);
                }
            }

            if (isRequired)
            {
                clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.ComponentModel.DataAnnotations.Required"));
            }

            if (settings.DecorateDataModelWithDataContract)
            {
                if (propertyNameAdjusted)
                {
                    string originalPropertyName = p.Key;
                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataMember", new CodeAttributeArgument("Name", new CodeSnippetExpression($"\"{originalPropertyName}\""))));
                }
                else
                {
                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataMember"));
                }
            }

            if (settings.DataAnnotationsEnabled)             //C#
            {
                AddValidationAttributes(propertySchema, clientProperty);
            }

            if (settings.DecorateDataModelWithPropertyName)             //C#
            {
                string originalPropertyName = p.Key;
                if (settings.UseSystemTextJson)
                {
                    //[System.Text.Json.Serialization.JsonPropertyName("name")]
                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("System.Text.Json.Serialization.JsonPropertyName", new CodeAttributeArgument(new CodeSnippetExpression($"\"{originalPropertyName}\""))));
                }
                else
                {
                    //[Newtonsoft.Json.JsonProperty(PropertyName = "name")]
                    clientProperty.CustomAttributes.Add(new CodeAttributeDeclaration("Newtonsoft.Json.JsonProperty", new CodeAttributeArgument("PropertyName", new CodeSnippetExpression($"\"{originalPropertyName}\""))));
                }
            }

            CreateMemberDocComment(p, clientProperty);
            typeDeclaration.Members.Add(clientProperty);
        }