Skip to content

Commit 122ed2e

Browse files
davidkallesenperkops
authored andcommitted
feat: improve namespace from settings
1 parent 7c5c470 commit 122ed2e

File tree

14 files changed

+303
-115
lines changed

14 files changed

+303
-115
lines changed

src/Atc.Rest.ApiGenerator.Contracts/Extensions/ApiOperationResponseModelExtensions.cs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,11 @@ public static IEnumerable<ApiOperationResponseModel> AppendBadRequestIfNeeded(
156156

157157
public static IEnumerable<ApiOperationResponseModel> AdjustNamespacesIfNeeded(
158158
this IEnumerable<ApiOperationResponseModel> responseModels,
159-
IList<ApiOperation> operationSchemaMappings)
159+
IList<ApiOperation> operationSchemaMappings,
160+
string contractNamespace)
160161
{
161-
if (responseModels is null)
162+
if (responseModels is null ||
163+
contractNamespace is null)
162164
{
163165
return Array.Empty<ApiOperationResponseModel>();
164166
}
@@ -170,22 +172,16 @@ public static IEnumerable<ApiOperationResponseModel> AdjustNamespacesIfNeeded(
170172
model.DataType.IsWellKnownSystemTypeName())
171173
{
172174
var operationSchemaMapping = operationSchemaMappings.First(x => x.Model.Name == model.DataType);
173-
if (operationSchemaMapping.Model.IsShared)
174-
{
175-
models.Add(
176-
model with
177-
{
178-
DataType = $"{ContentGeneratorConstants.Contracts}.{model.DataType}",
179-
});
180-
}
181-
else
182-
{
183-
models.Add(
184-
model with
185-
{
186-
DataType = $"{ContentGeneratorConstants.Contracts}.{operationSchemaMapping.ApiGroupName}.{model.DataType}",
187-
});
188-
}
175+
176+
contractNamespace = operationSchemaMapping.Model.IsShared
177+
? contractNamespace.Replace("[[apiGroupName]]", string.Empty, StringComparison.Ordinal).Trim('.')
178+
: contractNamespace.Replace("[[apiGroupName]]", operationSchemaMapping.ApiGroupName, StringComparison.Ordinal);
179+
180+
models.Add(
181+
model with
182+
{
183+
DataType = $"{contractNamespace}.{model.DataType}",
184+
});
189185
}
190186
else
191187
{

src/Atc.Rest.ApiGenerator.Framework.Minimal/ContentGenerators/ContentGeneratorServerProgram.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ public string Generate()
8484
if (SwaggerThemeMode != SwaggerThemeMode.None)
8585
{
8686
sb.AppendLine(8, "app.ConfigureSwagger(builder.Environment.ApplicationName);");
87+
sb.AppendLine();
8788
}
8889

89-
sb.AppendLine();
9090
sb.AppendLine(8, "app.UseHttpsRedirection();");
9191
sb.AppendLine(8, "app.UseHsts();");
9292
sb.AppendLine();

src/Atc.Rest.ApiGenerator.Framework.Minimal/ContentGenerators/ContentGeneratorServerResult.cs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,13 @@ private void AppendMethodContentStatusCodeOk(
9999
ContentGeneratorServerResultMethodParameters item,
100100
string resultName)
101101
{
102-
// TODO: byte[] bytes, string fileName
102+
if (item.ResponseModel.MediaType is not null &&
103+
item.ResponseModel.MediaType != MediaTypeNames.Application.Json)
104+
{
105+
sb.AppendLine(4, $"public static {resultName} Ok(byte[] bytes, string contentType, string fileName)");
106+
sb.AppendLine(8, "=> new(TypedResults.Bytes(bytes, contentType, fileName));");
107+
return;
108+
}
103109

104110
if (string.IsNullOrEmpty(item.ResponseModel.DataType))
105111
{
@@ -108,21 +114,28 @@ private void AppendMethodContentStatusCodeOk(
108114
return;
109115
}
110116

111-
if (item.ResponseModel.UseAsyncEnumerable)
117+
if (string.IsNullOrEmpty(item.ResponseModel.CollectionDataType))
112118
{
113-
sb.AppendLine(
114-
4,
115-
string.IsNullOrEmpty(item.ResponseModel.CollectionDataType)
116-
? $"public static {resultName} Ok(IAsyncEnumerable<{item.ResponseModel.DataType}> result)"
117-
: $"public static {resultName} Ok(IAsyncEnumerable<{item.ResponseModel.CollectionDataType}<{item.ResponseModel.DataType}>> result)");
119+
sb.AppendLine(4, $"public static {resultName} Ok({item.ResponseModel.DataType} result)");
118120
}
119121
else
120122
{
121-
sb.AppendLine(
122-
4,
123-
string.IsNullOrEmpty(item.ResponseModel.CollectionDataType)
124-
? $"public static {resultName} Ok({item.ResponseModel.DataType} result)"
125-
: $"public static {resultName} Ok({item.ResponseModel.CollectionDataType}<{item.ResponseModel.DataType}> result)");
123+
if (item.ResponseModel.UseAsyncEnumerable)
124+
{
125+
sb.AppendLine(
126+
4,
127+
item.ResponseModel.CollectionDataType == NameConstants.List
128+
? $"public static {resultName} Ok(IAsyncEnumerable<{item.ResponseModel.DataType}> result)"
129+
: $"public static {resultName} Ok(IAsyncEnumerable<{item.ResponseModel.CollectionDataType}<{item.ResponseModel.DataType}>> result)");
130+
}
131+
else
132+
{
133+
sb.AppendLine(
134+
4,
135+
item.ResponseModel.CollectionDataType == NameConstants.List
136+
? $"public static {resultName} Ok(IEnumerable<{item.ResponseModel.DataType}> result)"
137+
: $"public static {resultName} Ok({item.ResponseModel.CollectionDataType}<{item.ResponseModel.DataType}> result)");
138+
}
126139
}
127140

128141
sb.AppendLine(8, "=> new(TypedResults.Ok(result));");

src/Atc.Rest.ApiGenerator.Framework.Minimal/ContentGenerators/ContentGeneratorServerWebApplicationExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public string Generate()
2121
sb.AppendLine();
2222
sb.AppendLine("public static class WebApplicationExtensions");
2323
sb.AppendLine("{");
24+
sb.AppendLine(4, "[SuppressMessage(\"Spacing Rules\", \"SA1010:Opening Square Brackets Must Be Spaced Correctly\", Justification = \"OK.\")]");
2425
sb.AppendLine(4, "private static readonly string[] PatchHttpMethods = [\"patch\"];");
2526
sb.AppendLine();
2627
sb.AppendLine(4, "public static RouteHandlerBuilder MapPatch(");

src/Atc.Rest.ApiGenerator.Framework.Minimal/Factories/ContentGeneratorServerResultParametersFactory.cs

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ public static ContentGeneratorServerResultParameters Create(
3535
var okResponseModel = responseModels.Find(x => x.StatusCode == HttpStatusCode.OK) ??
3636
responseModels.Find(x => x.StatusCode == HttpStatusCode.Created);
3737

38-
if (ShouldAppendImplicitOperatorContent(
39-
httpStatusCodes,
40-
okResponseModel?.DataType,
41-
openApiOperation.Responses.IsSchemaUsingBinaryFormatForOkResponse()))
38+
if (ShouldAppendImplicitOperatorContent(httpStatusCodes))
4239
{
4340
var collectionDataType = okResponseModel?.CollectionDataType;
4441
var dataType = okResponseModel?.DataType;
@@ -60,37 +57,14 @@ public static ContentGeneratorServerResultParameters Create(
6057
}
6158

6259
private static bool ShouldAppendImplicitOperatorContent(
63-
ICollection<HttpStatusCode> httpStatusCodes,
64-
string? modelName,
65-
bool isSchemaUsingBinaryFormatForOkResponse)
60+
ICollection<HttpStatusCode> httpStatusCodes)
6661
{
6762
if (!httpStatusCodes.Contains(HttpStatusCode.OK) &&
6863
!httpStatusCodes.Contains(HttpStatusCode.Created))
6964
{
7065
return false;
7166
}
7267

73-
var httpStatusCode = HttpStatusCode.Continue; // Dummy
74-
if (httpStatusCodes.Contains(HttpStatusCode.OK))
75-
{
76-
httpStatusCode = HttpStatusCode.OK;
77-
}
78-
else if (httpStatusCodes.Contains(HttpStatusCode.Created))
79-
{
80-
httpStatusCode = HttpStatusCode.Created;
81-
}
82-
83-
if (httpStatusCode == HttpStatusCode.Created &&
84-
string.IsNullOrEmpty(modelName))
85-
{
86-
return false;
87-
}
88-
89-
if (isSchemaUsingBinaryFormatForOkResponse)
90-
{
91-
return false;
92-
}
93-
9468
return true;
9569
}
9670
}

src/Atc.Rest.ApiGenerator.Framework.Minimal/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
global using System.Net;
2+
global using System.Net.Mime;
23
global using System.Text;
34

45
global using Atc.CodeDocumentation.CodeComment;

src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerApiGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ public void GenerateEndpoints()
297297
GetRouteByApiGroupName(apiGroupName),
298298
ContentGeneratorConstants.EndpointDefinition,
299299
openApiDocument,
300+
settings.ContractsNamespace,
300301
settings.UsePartialClassForEndpoints);
301302

302303
var contentGenerator = new ContentGenerators.ContentGeneratorServerEndpoints(

src/Atc.Rest.ApiGenerator.Framework.Minimal/ProjectGenerator/ServerHostTestGenerator.cs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public async Task ScaffoldProjectFile()
7070
],
7171
[
7272
new("DocumentationFile", Attributes: null, @$"bin\Debug\net8.0\{settings.ProjectName}.xml"),
73-
new("NoWarn", Attributes: null, "$(NoWarn);1573;1591;1701;1702;1712;8618;"),
73+
new("NoWarn", Attributes: null, "$(NoWarn);1573;1591;1701;1702;1712;8618;NU1603;NU1608;"),
7474
],
7575
],
7676
[
@@ -177,8 +177,11 @@ public void GenerateEndpointHandlerStubs()
177177
var apiGroupName = openApiPath.GetApiGroupName();
178178

179179
var endpointsLocation = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsLocation);
180+
var endpointsNamespace = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.EndpointsNamespace);
181+
var contractsNamespace = LocationFactory.CreateWithApiGroupName(apiGroupName, settings.ContractsNamespace);
180182

181-
var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsLocation);
183+
var fullNamespace = NamespaceFactory.Create(settings.ProjectName, endpointsNamespace);
184+
var fullContractNamespace = NamespaceFactory.Create(settings.ProjectName.Replace("Tests", "Generated", StringComparison.Ordinal), contractsNamespace);
182185

183186
foreach (var openApiOperation in openApiPath.Value.Operations)
184187
{
@@ -192,7 +195,9 @@ public void GenerateEndpointHandlerStubs()
192195
fullNamespace,
193196
codeGeneratorAttribute,
194197
openApiPath.Value,
195-
openApiOperation.Value);
198+
openApiOperation.Value,
199+
fullContractNamespace,
200+
AspNetOutputType.MinimalApi);
196201

197202
var contentGenerator = new GenerateContentForClass(
198203
new CodeDocumentationTagsGenerator(),
@@ -253,21 +258,30 @@ public void MaintainGlobalUsings(
253258
var requiredUsings = new List<string>
254259
{
255260
"System.CodeDom.Compiler",
256-
"System.Text",
257-
"System.Text.Json",
258-
"System.Text.Json.Serialization",
259-
"System.Reflection",
260-
"Atc.XUnit",
261-
"Atc.Rest.Options",
262261
"AutoFixture",
263-
"Microsoft.AspNetCore.Hosting",
264-
"Microsoft.AspNetCore.Http",
265-
"Microsoft.Extensions.Configuration",
266-
"Microsoft.Extensions.DependencyInjection",
267-
"Xunit",
268-
apiProjectName,
269262
};
270263

264+
//// TODO: Maybe some is needed?
265+
////if (false)
266+
////{
267+
//// requiredUsings.Add("System.Reflection");
268+
//// requiredUsings.Add("System.Text");
269+
//// requiredUsings.Add("System.Text.Json");
270+
//// requiredUsings.Add("System.Text.Json.Serialization");
271+
//// requiredUsings.Add("Atc.Rest.Options");
272+
//// requiredUsings.Add("Atc.XUnit");
273+
//// requiredUsings.Add("Microsoft.AspNetCore.Hosting");
274+
//// requiredUsings.Add("Microsoft.AspNetCore.Http");
275+
//// requiredUsings.Add("Microsoft.Extensions.Configuration");
276+
//// requiredUsings.Add("Microsoft.Extensions.DependencyInjection");
277+
//// requiredUsings.Add("Xunit");
278+
////}
279+
280+
if (openApiDocument.IsUsingRequiredForSystemText(settings.IncludeDeprecatedOperations))
281+
{
282+
requiredUsings.Add("System.Text");
283+
}
284+
271285
if (openApiDocument.IsUsingRequiredForAtcRestResults())
272286
{
273287
requiredUsings.Add("Atc.Rest.Results");

src/Atc.Rest.ApiGenerator.Framework.Mvc/ContentGenerators/ContentGeneratorServerResult.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,11 @@ private void AppendMethodContentStatusCodeOk(
9797
ContentGeneratorServerResultMethodParameters item,
9898
string resultName)
9999
{
100-
if (item.ResponseModel.MediaType == MediaTypeNames.Application.Octet)
100+
if (item.ResponseModel.MediaType is not null &&
101+
item.ResponseModel.MediaType != MediaTypeNames.Application.Json)
101102
{
102-
sb.AppendLine(4, $"public static {resultName} Ok(byte[] bytes, string fileName)");
103-
sb.AppendLine(8, $"=> new {resultName}(ResultFactory.CreateFileContentResult(bytes, fileName));");
103+
sb.AppendLine(4, $"public static {resultName} Ok(byte[] bytes, string contentType, string fileName)");
104+
sb.AppendLine(8, $"=> new {resultName}(ResultFactory.CreateFileContentResult(bytes, fileName, contentType));");
104105
return;
105106
}
106107

@@ -170,7 +171,7 @@ private void AppendMethodContentForOtherStatusCodesThanOkWithProblemDetails(
170171
break;
171172
case HttpStatusCode.EarlyHints:
172173
sb.AppendLine(4, $"public static {resultName} {item.ResponseModel.StatusCode.ToNormalizedString()}()");
173-
sb.AppendLine(8, $"=> new {resultName}({nameof(Results.ResultFactory)}.{nameof(Results.ResultFactory.CreateContentResultWithProblemDetails)}({nameof(HttpStatusCode)}.{item.ResponseModel.StatusCode}));");
174+
sb.AppendLine(8, $"=> new {resultName}({nameof(Results.ResultFactory)}.{nameof(Results.ResultFactory.CreateContentResultWithProblemDetails)}({nameof(HttpStatusCode)}.{item.ResponseModel.StatusCode}, string.Empty));");
174175
break;
175176
case HttpStatusCode.Continue:
176177
case HttpStatusCode.SwitchingProtocols:
@@ -258,7 +259,7 @@ private void AppendMethodContentForOtherStatusCodesThanOkWithoutProblemDetails(
258259
break;
259260
case HttpStatusCode.EarlyHints:
260261
sb.AppendLine(4, $"public static {resultName} {item.ResponseModel.StatusCode.ToNormalizedString()}()");
261-
sb.AppendLine(8, $"=> new {resultName}({nameof(Results.ResultFactory)}.{nameof(Results.ResultFactory.CreateContentResult)}({nameof(HttpStatusCode)}.{item.ResponseModel.StatusCode}, string? message = null));");
262+
sb.AppendLine(8, $"=> new {resultName}({nameof(Results.ResultFactory)}.{nameof(Results.ResultFactory.CreateContentResult)}({nameof(HttpStatusCode)}.{item.ResponseModel.StatusCode}, string.Empty));");
262263
break;
263264
case HttpStatusCode.Continue:
264265
case HttpStatusCode.SwitchingProtocols:

src/Atc.Rest.ApiGenerator.Framework.Mvc/ProjectGenerator/ServerApiGenerator.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ public void GenerateEndpoints()
313313
GetRouteByApiGroupName(apiGroupName),
314314
ContentGeneratorConstants.Controller,
315315
openApiDocument,
316+
settings.ContractsNamespace,
316317
settings.UsePartialClassForEndpoints);
317318

318319
var contentGenerator = new ContentGenerators.ContentGeneratorServerController(
@@ -352,8 +353,10 @@ public void MaintainGlobalUsings(
352353
"Atc.Rest.Results",
353354
};
354355

355-
// TODO: Check for any use ??
356-
requiredUsings.Add("System.Net");
356+
if (openApiDocument.IsUsingRequiredForSystemNet(settings.IncludeDeprecatedOperations))
357+
{
358+
requiredUsings.Add("System.Net");
359+
}
357360

358361
if (openApiDocument.IsUsingRequiredForSystemTextJsonSerializationAndSystemRuntimeSerialization(settings.IncludeDeprecatedOperations))
359362
{

0 commit comments

Comments
 (0)