Skip to content

Commit c815412

Browse files
committed
chore: another batch of NRT fixes
Signed-off-by: Vincent Biret <[email protected]>
1 parent 0868da2 commit c815412

File tree

4 files changed

+111
-78
lines changed

4 files changed

+111
-78
lines changed

src/Microsoft.OpenApi.OData.Reader/Common/EdmModelHelper.cs

Lines changed: 72 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal static class EdmModelHelper
2323
/// Adds the derived types references together with their base type reference in the OneOf property of an OpenAPI schema.
2424
/// </summary>
2525
/// <returns>The OpenAPI schema with the list of derived types references and their base type references set in the OneOf property.</returns>
26-
internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel, OpenApiDocument document)
26+
internal static OpenApiSchema? GetDerivedTypesReferenceSchema(IEdmStructuredType structuredType, IEdmModel edmModel, OpenApiDocument document)
2727
{
2828
Utils.CheckArgumentNull(structuredType, nameof(structuredType));
2929
Utils.CheckArgumentNull(edmModel, nameof(edmModel));
@@ -38,7 +38,7 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
3838

3939
OpenApiSchema schema = new()
4040
{
41-
OneOf = new List<IOpenApiSchema>()
41+
OneOf = []
4242
};
4343

4444
var baseTypeSchema = new OpenApiSchemaReference(schemaElement.FullName(), document);
@@ -48,7 +48,7 @@ internal static OpenApiSchema GetDerivedTypesReferenceSchema(IEdmStructuredType
4848
{
4949
var derivedTypeSchema = new OpenApiSchemaReference(derivedType.FullName(), document);
5050
schema.OneOf.Add(derivedTypeSchema);
51-
};
51+
}
5252

5353
return schema;
5454
}
@@ -82,7 +82,7 @@ internal static bool NavigationRestrictionsAllowsNavigability(
8282
/// <param name="context">The OData context.</param>
8383
/// <param name="prefix">Optional: Identifier indicating whether it is a collection-valued non-indexed or single-valued navigation property.</param>
8484
/// <returns>The operation id generated from the given navigation property path.</returns>
85-
internal static string GenerateNavigationPropertyPathOperationId(ODataPath path, ODataContext context, string prefix = null)
85+
internal static string? GenerateNavigationPropertyPathOperationId(ODataPath path, ODataContext context, string? prefix = null)
8686
{
8787
IList<string> items = RetrieveNavigationPropertyPathsOperationIdSegments(path, context);
8888

@@ -110,24 +110,22 @@ internal static string GenerateNavigationPropertyPathOperationId(ODataPath path,
110110
/// <param name="context">The OData context.</param>
111111
/// <param name="prefix">Optional: Identifier indicating whether it is a collection-valued or single-valued complex property.</param>
112112
/// <returns>The operation id generated from the given complex property path.</returns>
113-
internal static string GenerateComplexPropertyPathOperationId(ODataPath path, ODataContext context, string prefix = null)
113+
internal static string? GenerateComplexPropertyPathOperationId(ODataPath path, ODataContext context, string? prefix = null)
114114
{
115115
IList<string> items = RetrieveNavigationPropertyPathsOperationIdSegments(path, context);
116116

117117
if (!items.Any())
118118
return null;
119119

120-
ODataComplexPropertySegment lastSegment = path.Segments.Skip(1).OfType<ODataComplexPropertySegment>()?.Last();
121-
Utils.CheckArgumentNull(lastSegment, nameof(lastSegment));
122-
123-
if (!string.IsNullOrEmpty(prefix))
124-
{
125-
items.Add(prefix + Utils.UpperFirstChar(lastSegment?.Identifier));
126-
}
127-
else
128-
{
129-
items.Add(Utils.UpperFirstChar(lastSegment?.Identifier));
130-
}
120+
if (path.Segments.Skip(1).OfType<ODataComplexPropertySegment>()?.Last()?.Identifier is string lastSegmentIdentifier)
121+
if (!string.IsNullOrEmpty(prefix))
122+
{
123+
items.Add(prefix + Utils.UpperFirstChar(lastSegmentIdentifier));
124+
}
125+
else
126+
{
127+
items.Add(Utils.UpperFirstChar(lastSegmentIdentifier));
128+
}
131129

132130
return GenerateNavigationPropertyPathOperationId(items);
133131
}
@@ -137,7 +135,7 @@ internal static string GenerateComplexPropertyPathOperationId(ODataPath path, OD
137135
/// </summary>
138136
/// <param name="items">The list of string values.</param>
139137
/// <returns>The generated navigation property operation id.</returns>
140-
private static string GenerateNavigationPropertyPathOperationId(IList<string> items)
138+
private static string? GenerateNavigationPropertyPathOperationId(IList<string> items)
141139
{
142140
if (!items.Any())
143141
return null;
@@ -155,10 +153,10 @@ internal static IList<string> RetrieveNavigationPropertyPathsOperationIdSegments
155153
{
156154
Utils.CheckArgumentNull(path, nameof(path));
157155

158-
IEdmNavigationSource navigationSource = (path.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource;
159-
Utils.CheckArgumentNull(navigationSource, nameof(navigationSource));
156+
if (path.FirstSegment is not ODataNavigationSourceSegment {NavigationSource: IEdmNavigationSource navigationSource})
157+
throw new InvalidOperationException("The first segment of the path is not a navigation source segment.");
160158

161-
IList<string> items = new List<string>
159+
var items = new List<string>
162160
{
163161
navigationSource.Name
164162
};
@@ -174,7 +172,7 @@ s is ODataOperationSegment ||
174172
s is ODataKeySegment);
175173
Utils.CheckArgumentNull(segments, nameof(segments));
176174

177-
string previousTypeCastSegmentId = null;
175+
string? previousTypeCastSegmentId = null;
178176
string pathHash = string.Empty;
179177

180178
foreach (var segment in segments)
@@ -185,15 +183,18 @@ s is ODataOperationSegment ||
185183
}
186184
else if (segment is ODataTypeCastSegment typeCastSegment
187185
&& path.Kind != ODataPathKind.TypeCast // ex: ~/NavSource/NavProp/TypeCast
188-
&& !(path.Kind == ODataPathKind.DollarCount && path.Segments.ElementAt(path.Segments.Count - 2)?.Kind == ODataSegmentKind.TypeCast)) // ex: ~/NavSource/NavProp/TypeCast/$count
186+
&& !(path.Kind == ODataPathKind.DollarCount && path.Segments[path.Segments.Count - 2]?.Kind == ODataSegmentKind.TypeCast)) // ex: ~/NavSource/NavProp/TypeCast/$count
189187
{
190188
// Only the last OData type cast segment identifier is added to the operation id
191-
items.Remove(previousTypeCastSegmentId);
192-
IEdmSchemaElement schemaElement = typeCastSegment.StructuredType as IEdmSchemaElement;
193-
previousTypeCastSegmentId = "As" + Utils.UpperFirstChar(schemaElement.Name);
194-
items.Add(previousTypeCastSegmentId);
189+
if (!string.IsNullOrEmpty(previousTypeCastSegmentId))
190+
items.Remove(previousTypeCastSegmentId);
191+
if (typeCastSegment.StructuredType is IEdmSchemaElement schemaElement)
192+
{
193+
previousTypeCastSegmentId = "As" + Utils.UpperFirstChar(schemaElement.Name);
194+
items.Add(previousTypeCastSegmentId);
195+
}
195196
}
196-
else if (segment is ODataOperationSegment operationSegment)
197+
else if (segment is ODataOperationSegment operationSegment && !string.IsNullOrEmpty(operationSegment.Identifier))
197198
{
198199
// Navigation property generated via composable function
199200
if (operationSegment.Operation is IEdmFunction function && context.Model.IsOperationOverload(function))
@@ -239,19 +240,20 @@ internal static string GenerateNavigationPropertyPathTagName(ODataPath path, ODa
239240
Utils.CheckArgumentNull(path, nameof(path));
240241
Utils.CheckArgumentNull(context, nameof(context));
241242

242-
IEdmNavigationSource navigationSource = (path.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource;
243+
if (path.FirstSegment is not ODataNavigationSourceSegment {NavigationSource: IEdmNavigationSource navigationSource })
244+
throw new InvalidOperationException("The first segment of the path is not a navigation source segment.");
243245

244-
IList<string> items = new List<string>
246+
var items = new List<string>
245247
{
246248
navigationSource.Name
247249
};
248250

249-
IEdmNavigationProperty navigationProperty = path.OfType<ODataNavigationPropertySegment>()?.Last()?.NavigationProperty;
250-
Utils.CheckArgumentNull(navigationProperty, nameof(navigationProperty));
251+
if (path.OfType<ODataNavigationPropertySegment>()?.Last()?.NavigationProperty is not IEdmNavigationProperty navigationProperty)
252+
throw new InvalidOperationException("The last segment of the path is not a navigation property segment.");
251253

252-
foreach (var segment in path.Segments.Skip(1).OfType<ODataNavigationPropertySegment>())
254+
foreach (var segment in path.Segments.Skip(1).OfType<ODataNavigationPropertySegment>().Select(static x => x.NavigationProperty))
253255
{
254-
if (segment.NavigationProperty == navigationProperty)
256+
if (segment == navigationProperty)
255257
{
256258
items.Add(navigationProperty.ToEntityType().Name);
257259
break;
@@ -260,12 +262,12 @@ internal static string GenerateNavigationPropertyPathTagName(ODataPath path, ODa
260262
{
261263
if (items.Count >= context.Settings.TagDepth - 1)
262264
{
263-
items.Add(segment.NavigationProperty.ToEntityType().Name);
265+
items.Add(segment.ToEntityType().Name);
264266
break;
265267
}
266268
else
267269
{
268-
items.Add(segment.NavigationProperty.Name);
270+
items.Add(segment.Name);
269271
}
270272
}
271273
}
@@ -284,23 +286,23 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
284286
Utils.CheckArgumentNull(path, nameof(path));
285287
Utils.CheckArgumentNull(context, nameof(context));
286288

287-
ODataComplexPropertySegment complexSegment = path.Segments.OfType<ODataComplexPropertySegment>()?.Last();
288-
Utils.CheckArgumentNull(complexSegment, nameof(complexSegment));
289+
if (path.Segments.OfType<ODataComplexPropertySegment>()?.Last() is not ODataComplexPropertySegment complexSegment)
290+
throw new InvalidOperationException("The last segment of the path is not a complex property segment.");
289291

290292
// Get the segment before the last complex type segment
291293
int complexSegmentIndex = path.Segments.IndexOf(complexSegment);
292-
ODataSegment preComplexSegment = path.Segments.ElementAt(complexSegmentIndex - 1);
294+
ODataSegment preComplexSegment = path.Segments[complexSegmentIndex - 1];
293295
int preComplexSegmentIndex = path.Segments.IndexOf(preComplexSegment);
294296

295297
while (preComplexSegment is ODataTypeCastSegment)
296298
{
297299
// Skip this segment,
298300
// Tag names don't include OData type cast segment identifiers
299301
preComplexSegmentIndex--;
300-
preComplexSegment = path.Segments.ElementAt(preComplexSegmentIndex);
302+
preComplexSegment = path.Segments[preComplexSegmentIndex];
301303
}
302304

303-
string tagName = null;
305+
string? tagName = null;
304306

305307
if (preComplexSegment is ODataNavigationSourceSegment sourceSegment)
306308
{
@@ -312,7 +314,7 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
312314
}
313315
else if (preComplexSegment is ODataKeySegment)
314316
{
315-
var prevKeySegment = path.Segments.ElementAt(preComplexSegmentIndex - 1);
317+
var prevKeySegment = path.Segments[preComplexSegmentIndex - 1];
316318
if (prevKeySegment is ODataNavigationPropertySegment)
317319
{
318320
tagName = GenerateNavigationPropertyPathTagName(path, context);
@@ -323,7 +325,7 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
323325
}
324326
}
325327

326-
List<string> tagNameItems = tagName?.Split('.').ToList();
328+
List<string> tagNameItems = tagName?.Split('.').ToList() ?? [];
327329

328330
if (tagNameItems.Count < context.Settings.TagDepth)
329331
{
@@ -340,41 +342,41 @@ internal static string GenerateComplexPropertyPathTagName(ODataPath path, ODataC
340342
/// <param name="context">The OData context.</param>
341343
/// <param name="includeListOrGetPrefix">Optional: Whether to include the List or Get prefix to the generated operation id.</param>
342344
/// <returns>The operation id prefix generated from the OData type cast path.</returns>
343-
internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path, ODataContext context, bool includeListOrGetPrefix = true)
345+
internal static string? GenerateODataTypeCastPathOperationIdPrefix(ODataPath path, ODataContext context, bool includeListOrGetPrefix = true)
344346
{
345347
// Get the segment before the last OData type cast segment
346-
ODataTypeCastSegment typeCastSegment = path.Segments.OfType<ODataTypeCastSegment>()?.Last();
347-
Utils.CheckArgumentNull(typeCastSegment, nameof(typeCastSegment));
348+
if (path.Segments.OfType<ODataTypeCastSegment>()?.Last() is not ODataTypeCastSegment typeCastSegment)
349+
throw new InvalidOperationException("The last segment of the path is not a type cast segment.");
348350

349351
int typeCastSegmentIndex = path.Segments.IndexOf(typeCastSegment);
350352

351353
// The segment 1 place before the last OData type cast segment
352-
ODataSegment secondLastSegment = path.Segments.ElementAt(typeCastSegmentIndex - 1);
354+
ODataSegment secondLastSegment = path.Segments[typeCastSegmentIndex - 1];
353355

354356
bool isIndexedCollValuedNavProp = false;
355357
if (secondLastSegment is ODataKeySegment)
356358
{
357359
// The segment 2 places before the last OData type cast segment
358-
ODataSegment thirdLastSegment = path.Segments.ElementAt(typeCastSegmentIndex - 2);
360+
ODataSegment thirdLastSegment = path.Segments[typeCastSegmentIndex - 2];
359361
if (thirdLastSegment is ODataNavigationPropertySegment)
360362
{
361363
isIndexedCollValuedNavProp = true;
362364
}
363365
}
364366

365-
ODataNavigationSourceSegment navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
366-
IEdmSingleton singleton = navigationSourceSegment?.NavigationSource as IEdmSingleton;
367-
IEdmEntitySet entitySet = navigationSourceSegment?.NavigationSource as IEdmEntitySet;
367+
ODataNavigationSourceSegment? navigationSourceSegment = path.FirstSegment as ODataNavigationSourceSegment;
368+
IEdmSingleton? singleton = navigationSourceSegment?.NavigationSource as IEdmSingleton;
369+
IEdmEntitySet? entitySet = navigationSourceSegment?.NavigationSource as IEdmEntitySet;
368370

369-
string operationId = null;
371+
string? operationId = null;
370372
if (secondLastSegment is ODataComplexPropertySegment complexSegment)
371373
{
372-
string listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
374+
string? listOrGet = includeListOrGetPrefix ? (complexSegment.Property.Type.IsCollection() ? "List" : "Get") : null;
373375
operationId = GenerateComplexPropertyPathOperationId(path, context, listOrGet);
374376
}
375377
else if (secondLastSegment is ODataNavigationPropertySegment navPropSegment)
376378
{
377-
string prefix = null;
379+
string? prefix = null;
378380
if (includeListOrGetPrefix)
379381
{
380382
prefix = navPropSegment?.NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many ? "List" : "Get";
@@ -391,22 +393,34 @@ internal static string GenerateODataTypeCastPathOperationIdPrefix(ODataPath path
391393
else
392394
{
393395
string entityTypeName = keySegment.EntityType.Name;
394-
string getPrefix = includeListOrGetPrefix ? "Get" : null;
396+
string? getPrefix = includeListOrGetPrefix ? "Get" : null;
395397
string operationName = $"{getPrefix}{Utils.UpperFirstChar(entityTypeName)}";
396398
if (keySegment.IsAlternateKey)
397399
{
398400
string alternateKeyName = string.Join("", keySegment.Identifier.Split(',').Select(static x => Utils.UpperFirstChar(x)));
399401
operationName = $"{operationName}By{alternateKeyName}";
400402
}
401-
operationId = (entitySet != null) ? entitySet.Name : singleton.Name;
403+
if (entitySet != null)
404+
{
405+
operationId = entitySet.Name;
406+
}
407+
else if (singleton != null)
408+
{
409+
operationId = singleton.Name;
410+
}
402411
operationId += $".{entityTypeName}.{operationName}";
403412
}
404413
}
405414
else if (secondLastSegment is ODataNavigationSourceSegment)
406415
{
407-
operationId = (entitySet != null)
408-
? entitySet.Name + "." + entitySet.EntityType.Name + $".{(includeListOrGetPrefix ? "List" : null)}" + Utils.UpperFirstChar(entitySet.EntityType.Name)
409-
: singleton.Name + "." + singleton.EntityType.Name + $".{(includeListOrGetPrefix ? "Get" : null)}" + Utils.UpperFirstChar(singleton.EntityType.Name);
416+
if (entitySet != null)
417+
{
418+
operationId = entitySet.Name + "." + entitySet.EntityType.Name + $".{(includeListOrGetPrefix ? "List" : null)}" + Utils.UpperFirstChar(entitySet.EntityType.Name);
419+
}
420+
else if (singleton != null)
421+
{
422+
operationId = singleton.Name + "." + singleton.EntityType.Name + $".{(includeListOrGetPrefix ? "Get" : null)}" + Utils.UpperFirstChar(singleton.EntityType.Name);
423+
}
410424
}
411425

412426
return operationId;

src/Microsoft.OpenApi.OData.Reader/Edm/EdmAnnotationExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ internal static class EdmVocabularyAnnotationExtensions
298298
{
299299
Utils.CheckArgumentNull(model, nameof(model));
300300
Utils.CheckArgumentNull(target, nameof(target));
301+
Utils.CheckArgumentNull(linkRel, nameof(linkRel));
301302

302303
return model.GetCollection<LinkType>(target, CoreConstants.Links)?.FirstOrDefault(x => x.Rel == linkRel);
303304
}

0 commit comments

Comments
 (0)