public ActionsGroupNode ReadController(Type type, AssemblyNode assemblyNode) { var controller = new ActionsGroupNode { Assembly = assemblyNode }; string routePrefix = null; var routePrefixAttribute = type.GetTypeInfo().GetCustomAttribute<RouteAttribute>(false) ?? type.GetTypeInfo().GetCustomAttribute<RouteAttribute>(); if (routePrefixAttribute != null) { routePrefix = routePrefixAttribute.Template; } controller.Name = type.Name.Replace("Controller", string.Empty); controller.Name = NameCleaner.Replace(controller.Name, string.Empty); controller.Documentation = documentation.GetDocumentation(type); foreach (var methodInfo in type.GetMethods().Where(x => x.IsPublic)) { if (methodInfo.GetCustomAttribute<NonActionAttribute>() != null) continue; if (methodInfo.IsSpecialName) continue; var action = ReadAction(routePrefix, methodInfo, controller); if (action != null) { controller.Actions.Add(action); } } return controller; }
public AssemblyNode ReadControllers(IEnumerable<Type> controllers) { var assemblyNode = new AssemblyNode(); foreach (var controllerType in controllers) { var controller = ReadController(controllerType, assemblyNode); if (controller.Actions.Any()) { assemblyNode.Controllers.Add(controller); } } return assemblyNode; }
public void WriteAssembly(AssemblyNode assemblyNode) { var controllers = assemblyNode.Controllers.OrderBy(x => x.Name).ToArray(); foreach (var controllerNode in controllers) { WriteController(controllerNode); } WriteViews(assemblyNode); if (assemblyNode.Types.Values.Any(x => x.IsObservable)) WriteKoViews(assemblyNode); var output = new StringBuilder(); foreach (var controllerNode in controllers) { output.AppendLine($"import * as {StringHelpers.ToCamelCase(controllerNode.Name)}Group from './{StringHelpers.ToCamelCase(controllerNode.Name)}';"); } output.AppendLine("import * as views from './views';"); output.AppendLine("import * as koViews from './ko-views';"); output.AppendLine($"import {{ loading }} from '{serviceHelpersModule}';"); output.AppendLine("export * from './views';"); output.AppendLine("export * from './ko-views';"); output.AppendLine($"export {{ loading }} from '{serviceHelpersModule}';"); output.AppendLine(); foreach (var controllerNode in controllers) { var moduleName = StringHelpers.ToCamelCase(controllerNode.Name); output.AppendLine($"export const {moduleName} = new {moduleName}Group.{controllerNode.Name}Controller();"); } output.AppendLine("export const services = {"); foreach (var controllerNode in controllers) { var moduleName = StringHelpers.ToCamelCase(controllerNode.Name); output.AppendLine($"{Tab}{moduleName}: {moduleName},"); } output.AppendLine($"{Tab}factories: {{"); foreach (var type in assemblyNode.Types.Values.Where(x => x.IsObservable)) { output.AppendLine($"{Tab}{Tab}create{StringHelpers.ToPascalCase(type.Name)}: (data: views.{type.CleanName}) => new koViews.{type.Name}(data),"); } output.AppendLine($"{Tab}}},"); output.AppendLine($"{Tab}loading: loading"); output.AppendLine("}"); output.AppendLine(); OutputModules.Add("services", output.ToString()); }
public ActionsGroupNode(AssemblyNode assembly, string name) => (Assembly, Name) = (assembly, name);
private void WriteKoViews(AssemblyNode assemblyNode) { var result = new StringBuilder(); result.AppendLine("import * as ko from 'knockout';"); result.AppendLine("import * as views from './views';"); result.AppendLine($"import * as validation from '{validationModule}';"); result.AppendLine($"import {{ loading }} from '{serviceHelpersModule}';"); result.AppendLine(); result.AppendLine("function toDate(date:string) {"); result.AppendLine($"{Tab}return date != undefined ? new Date(date) : undefined;"); result.AppendLine("}"); result.AppendLine("function fromDate(date:Date) {"); result.AppendLine($"{Tab}return date != undefined ? date.toISOString() : undefined;"); result.AppendLine("}"); result.AppendLine("function arrayChanged<T>(array: KnockoutObservableArray<T>, original: T[]) {"); result.AppendLine($"{Tab}return array() && (!original || array().length !== original.length);"); result.AppendLine("}"); result.AppendLine("function dateArrayChanged(array: KnockoutObservableArray<Date>, original: string[]) {"); result.AppendLine($"{Tab}return array() && (!original || array().length !== original.length);"); result.AppendLine("}"); foreach (var classNode in assemblyNode.Types.Where(x => x.Value.IsObservable)) { WriteKoTypeDefinition(classNode.Value, result); } OutputModules.Add("ko-views", result.ToString()); }
private void WriteViews(AssemblyNode assemblyNode) { StringBuilder result = new StringBuilder(); foreach (var classNode in assemblyNode.Types) { WriteTypeDefinition(classNode.Value, result, false); } OutputModules.Add("views", result.ToString()); }
private PropertyNode ReadProperty(PropertyInfo propertyInfo, Type[] newParents, AssemblyNode assembly, string version) { var propertyType = propertyInfo.PropertyType; var propertyNode = new PropertyNode { Name = StringHelpers.ToCamelCase(propertyInfo.Name), IsRequired = RemoveNullable(ref propertyType), Documentation = documentation.GetDocumentation(propertyInfo) }; var returnTypeAttributes = propertyInfo.GetCustomAttributes<ReturnTypeAttribute>().ToArray(); if (returnTypeAttributes.Any()) { if (returnTypeAttributes.Length == 1) { FillType(propertyNode, returnTypeAttributes[0].ReturnType, assembly, newParents, version); } else { propertyNode.Type = new TypeNode { Type = TypeIdentifier.Union, Union = returnTypeAttributes.Select(x => ReadType(x.ReturnType, assembly, newParents, version)).ToArray() }; } } else { FillType(propertyNode, propertyType, assembly, newParents, version); } var readOnly = propertyInfo.GetCustomAttribute<ReadOnlyAttribute>(); if (readOnly != null && readOnly.IsReadOnly) { propertyNode.IsReadOnly = true; } var editable = propertyInfo.GetCustomAttribute<EditableAttribute>(); if (editable != null && !editable.AllowEdit) { propertyNode.IsReadOnly = true; } propertyNode.IsObservable = propertyNode.Name != "id" && !propertyNode.IsReadOnly; GetConstraints(propertyInfo.GetCustomAttributes().ToArray(), propertyNode); return propertyNode; }
public List<PropertyNode> ReadProperties(Type type, Type[] parents, AssemblyNode assembly, string version) { var newParents = new Type[parents.Length + 1]; parents.CopyTo(newParents, 0); newParents[parents.Length] = type; return type.GetProperties() .Where(propertyInfo => !IsIgnored(propertyInfo)) .Select(propertyInfo => ReadProperty(propertyInfo, newParents, assembly, version)) .ToList(); }
private ReturnNode ReadReturn(Type responseType, AssemblyNode assembly, XElement documentationNode, string version) { var returnNode = new ReturnNode { Documentation = documentation.ParseDocumentation(documentationNode) }; FillType(returnNode, responseType, assembly, new Type[0], version); return returnNode; }
public TypeNode ReadType(Type parameterType, AssemblyNode assembly, Type[] parents, string version) { var parameterTypeName = parameterType.Name; var classNode = new TypeNode { Version = version }; classNode.Documentation = documentation.GetDocumentation(parameterType); if (parameterType.GetTypeInfo().IsEnum) { if (assembly.Types.ContainsKey(parameterTypeName)) { return assembly.Types[parameterTypeName]; } var enumNames = parameterType.GetTypeInfo().GetEnumNames(); var enumValues = parameterType.GetTypeInfo().GetEnumValues(); classNode.Name = parameterType.Name; classNode.Type = TypeIdentifier.Enum; classNode.Values = new List<EnumValueNode>(); for (var i = 0; i < enumValues.Length; i++) { var enumValue = new EnumValueNode { Name = enumNames[i], Value = Convert.ToInt32(enumValues.GetValue(i)), Documentation = documentation.GetDocumentation(parameterType, enumNames[i]) }; classNode.Values.Add(enumValue); } assembly.Types[classNode.Name] = classNode; } else if (parameterType == typeof(string)) { classNode.Type = TypeIdentifier.String; } else if (parameterType == typeof(long)) { classNode.Type = TypeIdentifier.Long; } else if (parameterType == typeof(int) || parameterType == typeof(short)) { classNode.Type = TypeIdentifier.Int; } else if (parameterType == typeof(float)) { classNode.Type = TypeIdentifier.Float; } else if (parameterType == typeof(double)) { classNode.Type = TypeIdentifier.Double; } else if (parameterType == typeof(DateTime)) { classNode.Type = TypeIdentifier.DateTime; } else if (parameterType == typeof(bool)) { classNode.Type = TypeIdentifier.Boolean; } else if (parameterType == typeof(decimal)) { classNode.Type = TypeIdentifier.Decimal; } else if (parameterType == typeof(Guid)) { classNode.Type = TypeIdentifier.Guid; } else if (parameterType == typeof(TimeSpan)) { classNode.Type = TypeIdentifier.TimeSpan; } else if (parameterType == typeof(object)) { classNode.Type = TypeIdentifier.Any; } else { if (assembly.Types.ContainsKey(parameterTypeName)) { return assembly.Types[parameterTypeName]; } classNode.IsReadOnly = true; classNode.Name = parameterType.Name; classNode.Type = TypeIdentifier.Object; assembly.Types[classNode.Name] = classNode; if (parents.All(x => x != parameterType)) { classNode.Properties = ReadProperties(parameterType, parents, assembly, version); } var jsonAttribute = parameterType.GetTypeInfo().GetCustomAttribute<JsonAttribute>(); if (jsonAttribute != null) { classNode.IsObservable = jsonAttribute.Observable; } } return classNode; }
private void FillType(ITypedNode typedNode, Type parameterType, AssemblyNode assembly, Type[] parents, string version) { if (Nullable.GetUnderlyingType(parameterType) == null && parameterType.GetTypeInfo().IsGenericType) { if (parameterType.ImplementsInterface(typeof(IDictionary<,>))) { typedNode.IsDictionary = true; parameterType = parameterType.GenericTypeArguments[1]; } else if (parameterType.ImplementsInterface(typeof(IEnumerable<>))) { typedNode.IsCollection = true; parameterType = parameterType.GenericTypeArguments[0]; } } if (parameterType.IsArray) { typedNode.IsCollection = true; parameterType = parameterType.GetElementType(); } typedNode.Type = ReadType(parameterType, assembly, parents, version); }
public ParameterNode ReadParameter(ParameterInfo parameterInfo, XElement documentationNode, AssemblyNode assembly, Dictionary<string, bool> routeParameters, string version) { var parameterNode = new ParameterNode { Name = parameterInfo.Name }; var parameterType = parameterInfo.ParameterType; parameterNode.Documentation = documentation.ParseDocumentation(documentationNode); parameterNode.IsRequired = RemoveNullable(ref parameterType); if (parameterInfo.DefaultValue != null) parameterNode.IsRequired = false; FillType(parameterNode, parameterType, assembly, new Type[0], version); if (routeParameters.ContainsKey(parameterInfo.Name)) { parameterNode.Position = ParameterPosition.Path; parameterNode.IsRequired = !routeParameters[parameterInfo.Name]; } else if (parameterInfo.GetCustomAttribute<FromQueryAttribute>() != null) { parameterNode.Position = ParameterPosition.Query; } else if (parameterInfo.GetCustomAttribute<FromBodyAttribute>() != null || parameterNode.Type.Type == TypeIdentifier.Object) { parameterNode.Position = ParameterPosition.Body; parameterNode.IsRequired = true; } else { parameterNode.Position = ParameterPosition.Query; } GetConstraints(parameterInfo.GetCustomAttributes().ToArray(), parameterNode); return parameterNode; }