diff --git a/Directory.Build.props b/Directory.Build.props index 5a5f8e2e..a0c6f0e2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -32,7 +32,7 @@ 0.3.0 0.18.0 0.2.0 - 0.25.2 + 0.25.3 0.12.2 0.9.0 0.9.0 diff --git a/generators/csharp/OpenApiCodegen.CSharp.Base/Client/OperationVisitor.cs b/generators/csharp/OpenApiCodegen.CSharp.Base/Client/OperationVisitor.cs index 701d9a96..e40da824 100644 --- a/generators/csharp/OpenApiCodegen.CSharp.Base/Client/OperationVisitor.cs +++ b/generators/csharp/OpenApiCodegen.CSharp.Base/Client/OperationVisitor.cs @@ -95,7 +95,7 @@ public override void Visit(OpenApiOperation operation, string httpMethod, Argume public override void Visit(OpenApiParameter param, Argument argument) { var info = param.Schema?.ResolveSchemaInfo(); - var dataType = inlineSchemas.ToInlineDataType(param.Schema) ?? CSharpInlineSchemas.AnyObject; + var dataType = inlineSchemas.SafeToInlineDataType(param.Schema, argument.Diagnostic) ?? CSharpInlineSchemas.AnyObject; argument.Builder?.SharedParameters.Add(new OperationParameter( RawName: param.Name, ParamName: CSharpNaming.ToParameterName(param.Name, options.ReservedIdentifiers()), @@ -133,7 +133,7 @@ public override void Visit(OpenApiResponse response, int? statusCode, Argument a Description: response.Description, Content: (from entry in (from c in content ?? Enumerable.Empty>() select (c.Key, c.Value.Schema)).DefaultIfEmpty((Key: "", Schema: null)) - let dataType = entry.Schema != null ? inlineSchemas.ToInlineDataType(entry.Schema) : null + let dataType = entry.Schema != null ? inlineSchemas.SafeToInlineDataType(entry.Schema, argument.Diagnostic) : null where entry.Key != "application/xml" // exclude xml, since we don't support it select new OperationResponseContentOption( MediaType: entry.Key, @@ -143,7 +143,7 @@ public override void Visit(OpenApiResponse response, int? statusCode, Argument a Headers: (from entry in response.Headers let required = entry.Required let info = entry.Schema?.ResolveSchemaInfo() - let dataType = inlineSchemas.ToInlineDataType(entry.Schema) + let dataType = inlineSchemas.SafeToInlineDataType(entry.Schema, argument.Diagnostic) select new OperationResponseHeader( RawName: entry.Name, ParamName: CSharpNaming.ToParameterName("header " + entry.Name, options.ReservedIdentifiers()), @@ -183,7 +183,7 @@ IEnumerable GetFormParams() => from param in mediaTypeSchemaInfo?.TryGetAnnotation()?.Properties let required = mediaTypeSchemaInfo?.TryGetAnnotation()?.RequiredProperties.Contains(param.Key) ?? false let info = param.Value?.ResolveSchemaInfo() - let dataType = inlineSchemas.ToInlineDataType(param.Value) + let dataType = inlineSchemas.SafeToInlineDataType(param.Value, argument.Diagnostic) select new OperationParameter( RawName: param.Key, ParamName: CSharpNaming.ToParameterName(param.Key, options.ReservedIdentifiers()), @@ -207,7 +207,7 @@ IEnumerable GetFormParams() => IEnumerable GetStandardParams() => from ct in new[] { mediaType } let info = ct.Schema?.ResolveSchemaInfo() - let dataType = inlineSchemas.ToInlineDataType(ct.Schema) + let dataType = inlineSchemas.SafeToInlineDataType(ct.Schema, argument.Diagnostic) select new OperationParameter( RawName: null, ParamName: CSharpNaming.ToParameterName(argument.Builder?.Operation.OperationId + " body", options.ReservedIdentifiers()), diff --git a/generators/csharp/OpenApiCodegen.CSharp.Base/MvcServer/CSharpControllerTransformer.cs b/generators/csharp/OpenApiCodegen.CSharp.Base/MvcServer/CSharpControllerTransformer.cs index 2d79a815..6ef67a75 100644 --- a/generators/csharp/OpenApiCodegen.CSharp.Base/MvcServer/CSharpControllerTransformer.cs +++ b/generators/csharp/OpenApiCodegen.CSharp.Base/MvcServer/CSharpControllerTransformer.cs @@ -6,6 +6,7 @@ using DarkPatterns.OpenApiCodegen.Handlebars; using DarkPatterns.OpenApi.CSharp; using DarkPatterns.OpenApiCodegen.CSharp.MvcServer.Templates; +using DarkPatterns.Json.Diagnostics; namespace DarkPatterns.OpenApiCodegen.CSharp.MvcServer; @@ -21,7 +22,16 @@ public SourceEntry TransformController(string groupName, OperationGroupData grou var resultOperations = new List(); var visitor = new ControllerOperationVisitor(settings.SchemaRegistry, options, controllerClassName: className); foreach (var (operation, method, path) in operations) - visitor.Visit(operation, method, new ControllerOperationVisitor.Argument(diagnostic, resultOperations.Add, CurrentPath: path)); + { + try + { + visitor.Visit(operation, method, new ControllerOperationVisitor.Argument(diagnostic, resultOperations.Add, CurrentPath: path)); + } + catch (Exception ex) + { + diagnostic.Diagnostics.AddRange(ex.ToDiagnostics(settings.SchemaRegistry.DocumentRegistry, operation.Metadata)); + } + } var template = new Templates.ControllerTemplate( Header: settings.Header(document.Id), diff --git a/lib/OpenApi.CSharp/CSharpInlineSchemas.cs b/lib/OpenApi.CSharp/CSharpInlineSchemas.cs index bd245e92..0337f1a6 100644 --- a/lib/OpenApi.CSharp/CSharpInlineSchemas.cs +++ b/lib/OpenApi.CSharp/CSharpInlineSchemas.cs @@ -22,7 +22,33 @@ public class CSharpInlineSchemas(CSharpSchemaOptions options, DocumentRegistry d public CSharpInlineDefinition? ToInlineDataType(JsonSchema? schema) { if (schema == null) return null; - return ToInlineDataType(schema.ResolveSchemaInfo()); + try + { + return ToInlineDataType(schema.ResolveSchemaInfo()); + } + catch (Exception ex) + { + throw new MultipleDiagnosticException([ + .. ex.ToDiagnostics(documentRegistry, schema.Metadata), + ]); + } + } + + [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull(nameof(schema))] + public CSharpInlineDefinition? SafeToInlineDataType(JsonSchema? schema, OpenApiTransformDiagnostic diagnostic) + { + if (schema == null) return null; + try + { + return ToInlineDataType(schema.ResolveSchemaInfo()); + } + catch (Exception ex) + { + diagnostic.Diagnostics.AddRange([ + .. ex.ToDiagnostics(documentRegistry, schema.Metadata), + ]); + return CSharpInlineSchemas.AnyObject; + } } [return: NotNullIfNotNull(nameof(schema))] @@ -226,4 +252,4 @@ _ when int.TryParse(statusCode, out var numeric) && HttpStatusCodes.StatusCodeNa }; } } -} \ No newline at end of file +} diff --git a/lib/OpenApi.CSharp/CSharpSchemaSourceProvider.cs b/lib/OpenApi.CSharp/CSharpSchemaSourceProvider.cs index ae05b77e..d1df7970 100644 --- a/lib/OpenApi.CSharp/CSharpSchemaSourceProvider.cs +++ b/lib/OpenApi.CSharp/CSharpSchemaSourceProvider.cs @@ -103,7 +103,7 @@ private Templates.ObjectModel ToObjectModel(string className, JsonSchemaInfo sch Templates.ModelVar[] vars = (from entry in properties let req = required.Contains(entry.Key) - let dataType = inlineSchemas.ToInlineDataType(entry.Value.EffectiveSchema) + let dataType = inlineSchemas.SafeToInlineDataType(entry.Value.EffectiveSchema, diagnostic) let resolved = objectModel.LegacyOptionalBehavior && !req ? dataType.MakeNullable() : dataType select new Templates.ModelVar( BaseName: entry.Key, diff --git a/lib/OpenApiCodegen.Server.Mvc.Test/ComprehensiveTransformsShould.cs b/lib/OpenApiCodegen.Server.Mvc.Test/ComprehensiveTransformsShould.cs index 6321c693..b2cb408b 100644 --- a/lib/OpenApiCodegen.Server.Mvc.Test/ComprehensiveTransformsShould.cs +++ b/lib/OpenApiCodegen.Server.Mvc.Test/ComprehensiveTransformsShould.cs @@ -98,8 +98,10 @@ public void Reports_diagnostics_for_bad_2_yaml() { Assert.IsType(diag); Assert.Equal("proj://embedded/bad.2.yaml", diag.Location.RetrievalUri.OriginalString); - Assert.Equal(16, diag.Location.Range?.Start.Line); - Assert.Equal(17, diag.Location.Range?.Start.Column); + Assert.Equal(18, diag.Location.Range?.Start.Line); + Assert.Equal(25, diag.Location.Range?.Start.Column); + Assert.Equal(18, diag.Location.Range?.End.Line); + Assert.Equal(55, diag.Location.Range?.End.Column); } ); } diff --git a/lib/TestApp.Bad/OpenApiCodegen.Server.Mvc.TestApp.Bad.csproj b/lib/TestApp.Bad/OpenApiCodegen.Server.Mvc.TestApp.Bad.csproj index 1468bb2e..6d2f01e1 100644 --- a/lib/TestApp.Bad/OpenApiCodegen.Server.Mvc.TestApp.Bad.csproj +++ b/lib/TestApp.Bad/OpenApiCodegen.Server.Mvc.TestApp.Bad.csproj @@ -11,8 +11,8 @@ - - + +