public static string ReadServiceNameOption(this ArgsReader args) { string serviceName = args.ReadOption("serviceName"); if (serviceName != null && ServiceDefinitionUtility.IsValidName(serviceName)) { throw new ArgsReaderException($"Invalid service name '{serviceName}'."); } return(serviceName); }
private void Convert(SwaggerParserContext context) { if (m_swaggerService.Swagger == null) { m_errors.Add(context.CreateError("swagger field is missing.")); } else if (m_swaggerService.Swagger != SwaggerUtility.SwaggerVersion) { m_errors.Add(context.CreateError($"swagger should be '{SwaggerUtility.SwaggerVersion}'.", "swagger")); } if (m_swaggerService.Info == null) { m_errors.Add(context.CreateError("info is missing.")); } var name = m_serviceName; if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { m_errors.Add(context.CreateError("ServiceName generator option is not a valid service name.")); } if (name == null) { name = m_swaggerService.Info?.Identifier; } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { m_errors.Add(context.CreateError("info/x-identifier is not a valid service name.", "info/x-identifier")); } if (name == null && m_swaggerService.Info?.Title is string title) { name = CodeGenUtility.ToPascalCase(title); } if (name == null) { m_errors.Add(context.CreateError("info/title is missing.", "info")); } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { m_errors.Add(context.CreateError("info/title is not a valid service name.", "info/title")); } var attributes = new List <ServiceAttributeInfo>(); var version = m_swaggerService.Info?.Version; if (!string.IsNullOrWhiteSpace(version)) { attributes.Add(new ServiceAttributeInfo("info", new[] { new ServiceAttributeParameterInfo("version", version !, context.CreatePart("info/version") !) },
protected override FileGeneratorSettings CreateSettings(ArgsReader args) { var serviceName = args.ReadOption("service-name"); if (serviceName != null && ServiceDefinitionUtility.IsValidName(serviceName)) { throw new ArgsReaderException($"Invalid service name '{serviceName}'."); } return(new SwaggerGeneratorSettings { GeneratesFsd = args.ReadFlag("fsd"), GeneratesJson = args.ReadFlag("json"), ServiceName = serviceName, }); }
private HttpServiceInfo(ServiceInfo serviceInfo) { Service = serviceInfo; foreach (var parameter in GetHttpParameters(serviceInfo)) { if (parameter.Name == "url") { Url = parameter.Value; } else { AddInvalidHttpParameterError(parameter); } } foreach (var descendant in serviceInfo.GetElementAndDescendants().OfType <ServiceElementWithAttributesInfo>()) { var httpAttributes = descendant.GetAttributes("http"); if (httpAttributes.Count != 0) { if (!(descendant is ServiceInfo || descendant is ServiceMethodInfo || descendant is ServiceFieldInfo || descendant is ServiceErrorSetInfo || descendant is ServiceErrorInfo)) { AddValidationError(ServiceDefinitionUtility.CreateUnexpectedAttributeError(httpAttributes[0])); } else if (httpAttributes.Count > 1) { AddValidationError(ServiceDefinitionUtility.CreateDuplicateAttributeError(httpAttributes[1])); } } } Methods = serviceInfo.Methods.Select(x => new HttpMethodInfo(x, serviceInfo)).ToList(); ErrorSets = serviceInfo.ErrorSets.Select(x => new HttpErrorSetInfo(x)).ToList(); var methodsByRoute = Methods.OrderBy(x => x, HttpMethodInfo.ByRouteComparer).ToList(); for (int index = 1; index < methodsByRoute.Count; index++) { var left = methodsByRoute[index - 1]; var right = methodsByRoute[index]; if (HttpMethodInfo.ByRouteComparer.Compare(left, right) == 0) { AddValidationError(new ServiceDefinitionError($"Methods '{left.ServiceMethod.Name}' and '{right.ServiceMethod.Name}' have the same route: {right.Method} {right.Path}", right.ServiceMethod.Position)); } } }
/// <summary> /// Called to execute the code generator application. /// </summary> /// <param name="args">The command-line arguments.</param> /// <returns>The exit code.</returns> public int Run(IReadOnlyList <string> args) { try { var argsReader = new ArgsReader(args); if (argsReader.ReadHelpFlag()) { foreach (string line in Description) { System.Console.WriteLine(line); } System.Console.WriteLine(); WriteUsage(); return(0); } var generator = CreateGenerator(argsReader); generator.GeneratorName = s_assemblyName; if (SupportsCustomIndent) { string indentText = argsReader.ReadIndentOption(); if (indentText != null) { generator.IndentText = indentText; } } if (SupportsCustomNewLine) { string newLine = argsReader.ReadNewLineOption(); if (newLine != null) { generator.NewLine = newLine; } } string serviceName = argsReader.ReadServiceNameOption(); bool shouldClean = SupportsClean && argsReader.ReadCleanFlag(); bool isQuiet = argsReader.ReadQuietFlag(); bool isVerify = argsReader.ReadVerifyFlag(); bool isDryRun = argsReader.ReadDryRunFlag(); string inputPath = argsReader.ReadArgument(); if (inputPath == null) { throw new ArgsReaderException("Missing input path."); } string outputPath = argsReader.ReadArgument(); if (outputPath == null) { throw new ArgsReaderException("Missing output path."); } argsReader.VerifyComplete(); NamedText input; if (inputPath == "-") { input = new NamedText("", System.Console.In.ReadToEnd()); } else { if (!File.Exists(inputPath)) { throw new ApplicationException("Input file does not exist: " + inputPath); } input = new NamedText(Path.GetFileName(inputPath), File.ReadAllText(inputPath)); } ServiceInfo service; if (ServiceDefinitionUtility.DetectFormat(input) == ServiceDefinitionFormat.Swagger) { service = new SwaggerParser { ServiceName = serviceName }.ParseDefinition(input); } else { if (serviceName != null) { throw new ArgsReaderException("--serviceName not supported for FSD input."); } service = new FsdParser().ParseDefinition(input); } PrepareGenerator(generator, service, outputPath); var output = generator.GenerateOutput(service); if (SupportsSingleOutput && !outputPath.EndsWith("/", StringComparison.Ordinal) && !outputPath.EndsWith("\\", StringComparison.Ordinal) && !Directory.Exists(outputPath)) { if (output.NamedTexts.Count > 1) { throw new InvalidOperationException("Multiple outputs not expected."); } if (output.NamedTexts.Count == 1) { var namedText = output.NamedTexts[0]; if (outputPath == "-") { System.Console.Write(namedText.Text); } else if (ShouldWriteByteOrderMark(namedText.Name)) { File.WriteAllText(outputPath, namedText.Text, s_utf8WithBom); } else { File.WriteAllText(outputPath, namedText.Text); } } } else { var namedTextsToWrite = new List <NamedText>(); foreach (var namedText in output.NamedTexts) { string existingFilePath = Path.Combine(outputPath, namedText.Name); if (File.Exists(existingFilePath)) { // ignore CR when comparing files if (namedText.Text.Replace("\r", "") != File.ReadAllText(existingFilePath).Replace("\r", "")) { namedTextsToWrite.Add(namedText); if (!isQuiet) { System.Console.WriteLine("changed " + namedText.Name); } } } else { namedTextsToWrite.Add(namedText); if (!isQuiet) { System.Console.WriteLine("added " + namedText.Name); } } } var namesToDelete = new List <string>(); if (shouldClean && output.PatternsToClean.Count != 0) { var directoryInfo = new DirectoryInfo(outputPath); if (directoryInfo.Exists) { foreach (string nameMatchingPattern in FindNamesMatchingPatterns(directoryInfo, output.PatternsToClean)) { if (output.NamedTexts.All(x => x.Name != nameMatchingPattern)) { namesToDelete.Add(nameMatchingPattern); if (!isQuiet) { System.Console.WriteLine("removed " + nameMatchingPattern); } } } } } if (isVerify) { return(namedTextsToWrite.Count != 0 || namesToDelete.Count != 0 ? 1 : 0); } if (!isDryRun) { if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } foreach (var namedText in namedTextsToWrite) { string outputFilePath = Path.Combine(outputPath, namedText.Name); string outputFileDirectoryPath = Path.GetDirectoryName(outputFilePath); if (outputFileDirectoryPath != null && outputFileDirectoryPath != outputPath && !Directory.Exists(outputFileDirectoryPath)) { Directory.CreateDirectory(outputFileDirectoryPath); } if (ShouldWriteByteOrderMark(namedText.Name)) { File.WriteAllText(outputFilePath, namedText.Text, s_utf8WithBom); } else { File.WriteAllText(outputFilePath, namedText.Text); } } foreach (string nameToDelete in namesToDelete) { File.Delete(Path.Combine(outputPath, nameToDelete)); } } } return(0); } catch (Exception exception) { if (exception is ApplicationException || exception is ArgsReaderException || exception is ServiceDefinitionException) { System.Console.Error.WriteLine(exception.Message); if (exception is ArgsReaderException) { System.Console.Error.WriteLine(); WriteUsage(); } return(2); } else { System.Console.Error.WriteLine(exception.ToString()); return(3); } } }
public async Task <ServiceResult <GenerateResponseDto> > GenerateAsync(GenerateRequestDto request, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } try { var input = new NamedText(request.Definition?.Name ?? "", request.Definition?.Text ?? ""); bool isSwagger = ServiceDefinitionUtility.DetectFormat(input) == ServiceDefinitionFormat.Swagger; var service = isSwagger ? new SwaggerParser().ParseDefinition(input) : new FsdParser().ParseDefinition(input); var generatorName = request.Generator?.Name; switch (generatorName) { case "csharp": return(ServiceResult.Success(GenerateCode(() => new CSharpGenerator(), g => g.GenerateOutput(service)))); case "javascript": return(ServiceResult.Success(GenerateCode(() => new JavaScriptGenerator(), g => g.GenerateOutput(service)))); case "typescript": return(ServiceResult.Success(GenerateCode(() => new JavaScriptGenerator { TypeScript = true }, g => g.GenerateOutput(service)))); case "markdown": return(ServiceResult.Success(GenerateCode(() => new MarkdownGenerator(), g => g.GenerateOutput(service)))); case "fsd": return(ServiceResult.Success(GenerateCode(() => new FsdGenerator(), g => g.GenerateOutput(service)))); case "swagger-json": return(ServiceResult.Success(GenerateCode(() => new SwaggerGenerator(), g => g.GenerateOutput(service)))); case "swagger-yaml": return(ServiceResult.Success(GenerateCode(() => new SwaggerGenerator { Yaml = true }, g => g.GenerateOutput(service)))); case "asp-net-web-api": return(ServiceResult.Success(GenerateCode(() => new AspNetGenerator(), g => g.GenerateOutput(service)))); case "crash": throw new InvalidOperationException("Intentional exception for diagnostic purposes."); default: return(ServiceResult.Failure(ServiceErrors.CreateInvalidRequest($"Unrecognized generator '{generatorName}'."))); } } catch (ServiceDefinitionException exception) { return(ServiceResult.Success(new GenerateResponseDto { Failure = new FailureDto { Message = exception.Error, Line = exception.Position.LineNumber, Column = exception.Position.ColumnNumber, }, })); } }
private void AddRequestFields(IList <ServiceFieldInfo> requestFields, SwaggerParameter swaggerParameter, string serviceMethodName, string httpMethod, SwaggerService swaggerService, NamedTextPosition position) { string kind = swaggerParameter.In; if (kind == SwaggerParameterKind.Path || kind == SwaggerParameterKind.Query || kind == SwaggerParameterKind.Header) { string typeName = swaggerService.TryGetFacilityTypeName(swaggerParameter, position); if (typeName != null) { if (typeName.EndsWith("[]", StringComparison.Ordinal)) { typeName = "string"; } var attributes = new List <ServiceAttributeInfo>(); if (swaggerParameter.Obsolete.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } string fieldName = swaggerParameter.Identifier ?? swaggerParameter.Name; if (!ServiceDefinitionUtility.IsValidName(fieldName)) { fieldName = CodeGenUtility.ToCamelCase(fieldName); } if (kind == SwaggerParameterKind.Query) { var parameters = new List <ServiceAttributeParameterInfo>(); if (httpMethod != "GET") { parameters.Add(new ServiceAttributeParameterInfo("from", "query")); } if (fieldName != swaggerParameter.Name) { parameters.Add(new ServiceAttributeParameterInfo("name", swaggerParameter.Name)); } if (parameters.Count != 0) { attributes.Add(new ServiceAttributeInfo("http", parameters)); } } else if (kind == SwaggerParameterKind.Header) { attributes.Add(new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "header"), new ServiceAttributeParameterInfo("name", swaggerParameter.Name), })); } requestFields.Add(new ServiceFieldInfo( fieldName, typeName: typeName, attributes: attributes, summary: PrepareSummary(swaggerParameter.Description), position: position)); } } else if (kind == SwaggerParameterKind.Body) { var bodySchema = swaggerService.ResolveDefinition(swaggerParameter.Schema, position); if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object && (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Request", StringComparison.OrdinalIgnoreCase))) { AddFieldsFromSchema(requestFields, swaggerService, position, bodySchema); } else { string typeName = bodySchema.Key ?? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position)); if (typeName != null) { requestFields.Add(new ServiceFieldInfo( bodySchema.Value.Identifier ?? "body", typeName: typeName, attributes: new[] { new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "body", position) }) }, summary: PrepareSummary(swaggerParameter.Description), position: position)); } } } }
private void AddServiceMethod(IList <IServiceMemberInfo> members, string method, string path, SwaggerOperation swaggerOperation, IList <SwaggerParameter> swaggerOperationsParameters, SwaggerService swaggerService, SwaggerParserContext context) { if (swaggerOperation == null) { return; } var position = context.CreatePosition(); path = s_pathParameter.Replace(path, match => { string paramName = match.ToString().Substring(1, match.Length - 2); if (!ServiceDefinitionUtility.IsValidName(paramName)) { paramName = CodeGenUtility.ToCamelCase(paramName); } return($"{{{paramName}}}"); }); string name = CodeGenUtility.ToCamelCase(swaggerOperation.OperationId); if (!ServiceDefinitionUtility.IsValidName(name)) { name = CodeGenUtility.ToCamelCase($"{method} {path}"); } var httpAttributeValues = new List <ServiceAttributeParameterInfo> { new ServiceAttributeParameterInfo("method", method), new ServiceAttributeParameterInfo("path", path), }; var requestFields = new List <ServiceFieldInfo>(); foreach (var swaggerParameter in swaggerOperationsParameters.EmptyIfNull().Concat(swaggerOperation.Parameters.EmptyIfNull())) { AddRequestFields(requestFields, swaggerService.ResolveParameter(swaggerParameter, position), name, method, swaggerService, position); } var responseFields = new List <ServiceFieldInfo>(); var swaggerResponsePairs = swaggerOperation.Responses.EmptyIfNull() .Where(x => x.Key[0] == '2' || x.Key[0] == '3' || !string.IsNullOrEmpty(x.Value.Identifier)).ToList(); foreach (var swaggerResponsePair in swaggerResponsePairs) { AddResponseFields(responseFields, swaggerResponsePair.Key, swaggerService.ResolveResponse(swaggerResponsePair.Value, position), name, httpAttributeValues, swaggerOperation.Responses.Count == 1, swaggerService, position); } var attributes = new List <ServiceAttributeInfo> { new ServiceAttributeInfo("http", httpAttributeValues) }; if (swaggerOperation.Deprecated.GetValueOrDefault()) { attributes.Add(new ServiceAttributeInfo("obsolete")); } members.Add(new ServiceMethodInfo( name: name, requestFields: requestFields, responseFields: responseFields, attributes: attributes, summary: PrepareSummary(swaggerOperation.Summary), remarks: SplitRemarks(swaggerOperation.Description), position: position)); }
private ServiceInfo ConvertSwaggerService(SwaggerService swaggerService, SwaggerParserContext context) { if (swaggerService.Swagger == null) { throw context.CreateException("swagger field is missing."); } if (swaggerService.Swagger != SwaggerUtility.SwaggerVersion) { throw context.CreateException($"swagger should be '{SwaggerUtility.SwaggerVersion}'.", "swagger"); } if (swaggerService.Info == null) { throw context.CreateException("info is missing."); } string name = ServiceName; if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("ServiceName generator option is not a valid service name."); } if (name == null) { name = swaggerService.Info?.Identifier; } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("info/x-identifier is not a valid service name.", "info/x-identifier"); } if (name == null) { name = CodeGenUtility.ToPascalCase(swaggerService.Info?.Title); } if (name == null) { throw context.CreateException("info/title is missing.", "info"); } if (name != null && !ServiceDefinitionUtility.IsValidName(name)) { throw context.CreateException("info/title is not a valid service name.", "info/title"); } var attributes = new List <ServiceAttributeInfo>(); string version = swaggerService.Info?.Version; if (!string.IsNullOrWhiteSpace(version)) { attributes.Add(new ServiceAttributeInfo("info", new[] { new ServiceAttributeParameterInfo("version", version, context.CreatePosition("info/version")) }, context.CreatePosition("info"))); } string scheme = GetBestScheme(swaggerService.Schemes); string host = swaggerService.Host; string basePath = swaggerService.BasePath ?? ""; if (!string.IsNullOrWhiteSpace(host) && !string.IsNullOrWhiteSpace(scheme)) { string url = new UriBuilder(scheme, host) { Path = basePath }.Uri.AbsoluteUri; attributes.Add(new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("url", url, context.CreatePosition()) }, context.CreatePosition())); } var position = context.CreatePosition(); var members = new List <IServiceMemberInfo>(); foreach (var swaggerPath in swaggerService.Paths.EmptyIfNull()) { var swaggerOperations = swaggerPath.Value; var operationsContext = context.CreateContext("paths/swaggerPath"); swaggerService.ResolveOperations(ref swaggerOperations, ref operationsContext); AddServiceMethod(members, "GET", swaggerPath.Key, swaggerOperations.Get, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("get")); AddServiceMethod(members, "POST", swaggerPath.Key, swaggerOperations.Post, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("post")); AddServiceMethod(members, "PUT", swaggerPath.Key, swaggerOperations.Put, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("put")); AddServiceMethod(members, "DELETE", swaggerPath.Key, swaggerOperations.Delete, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("delete")); AddServiceMethod(members, "OPTIONS", swaggerPath.Key, swaggerOperations.Options, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("options")); AddServiceMethod(members, "HEAD", swaggerPath.Key, swaggerOperations.Head, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("head")); AddServiceMethod(members, "PATCH", swaggerPath.Key, swaggerOperations.Patch, swaggerOperations.Parameters, swaggerService, operationsContext.CreateContext("patch")); } foreach (var swaggerDefinition in swaggerService.Definitions.EmptyIfNull()) { if ((swaggerDefinition.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object && !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Request", StringComparison.OrdinalIgnoreCase)) && !members.OfType <ServiceMethodInfo>().Any(x => swaggerDefinition.Key.Equals(x.Name + "Response", StringComparison.OrdinalIgnoreCase)) && !swaggerService.IsFacilityError(swaggerDefinition) && swaggerService.TryGetFacilityResultOfType(swaggerDefinition, position) == null) { AddServiceDto(members, swaggerDefinition.Key, swaggerDefinition.Value, swaggerService, context.CreatePosition("definitions/" + swaggerDefinition.Key)); } } return(new ServiceInfo(name, members: members, attributes: attributes, summary: PrepareSummary(swaggerService.Info?.Title), remarks: SplitRemarks(swaggerService.Info?.Description), position: context.CreatePosition())); }
private CSharpServiceInfo(ServiceInfo serviceInfo, out IReadOnlyList <ServiceDefinitionError> errors) { Service = serviceInfo; m_fieldPropertyNames = new Dictionary <ServiceFieldInfo, string>(); var validationErrors = new List <ServiceDefinitionError>(); foreach (var descendant in serviceInfo.GetElementAndDescendants().OfType <ServiceElementWithAttributesInfo>()) { var csharpAttributes = descendant.GetAttributes("csharp"); if (csharpAttributes.Count == 1) { var csharpAttribute = csharpAttributes[0]; if (descendant is ServiceInfo || descendant is ServiceFieldInfo) { foreach (var parameter in csharpAttribute.Parameters) { if (parameter.Name == "namespace" && descendant is ServiceInfo) { m_namespace = parameter.Value; } else if (parameter.Name == "name" && descendant is ServiceFieldInfo field) { m_fieldPropertyNames[field] = parameter.Value; } else { validationErrors.Add(ServiceDefinitionUtility.CreateUnexpectedAttributeParameterError(csharpAttribute.Name, parameter)); } } } else { validationErrors.Add(ServiceDefinitionUtility.CreateUnexpectedAttributeError(csharpAttribute)); } } else if (csharpAttributes.Count > 1) { validationErrors.Add(ServiceDefinitionUtility.CreateDuplicateAttributeError(csharpAttributes[1])); } } var typeName = new HashSet <string>(StringComparer.OrdinalIgnoreCase) { CSharpUtility.GetInterfaceName(serviceInfo) }; void CheckTypeName(string name, ServiceDefinitionPosition?position) { if (!typeName !.Add(name)) { validationErrors !.Add(new ServiceDefinitionError($"Element generates duplicate C# type '{name}'.", position)); } } foreach (var member in serviceInfo.Members) { if (member is ServiceMethodInfo method) { CheckTypeName(CSharpUtility.GetRequestDtoName(method), method.Position); CheckTypeName(CSharpUtility.GetResponseDtoName(method), method.Position); } else if (member is ServiceDtoInfo dto) { CheckTypeName(CSharpUtility.GetDtoName(dto), dto.Position); } else if (member is ServiceEnumInfo @enum) { CheckTypeName(CSharpUtility.GetEnumName(@enum), @enum.Position); } else if (member is ServiceErrorSetInfo errorSet) { CheckTypeName(CSharpUtility.GetErrorSetName(errorSet), errorSet.Position); } else { throw new InvalidOperationException($"Unknown member type {member.GetType().FullName}"); } } errors = validationErrors; }
private protected void AddInvalidHttpParameterError(ServiceAttributeParameterInfo parameter) => AddValidationError(ServiceDefinitionUtility.CreateUnexpectedAttributeParameterError("http", parameter));