Skip to content

Commit 5362d83

Browse files
committed
chore: additional NRT fixes
Signed-off-by: Vincent Biret <[email protected]>
1 parent 0de5fb1 commit 5362d83

File tree

8 files changed

+138
-111
lines changed

8 files changed

+138
-111
lines changed

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.OData.Edm;
1010
using Microsoft.OData.Edm.Vocabularies;
1111
using Microsoft.OpenApi.Any;
12+
using Microsoft.OpenApi.Interfaces;
1213
using Microsoft.OpenApi.Models;
1314
using Microsoft.OpenApi.OData.Common;
1415
using Microsoft.OpenApi.OData.Generator;
@@ -24,7 +25,7 @@ namespace Microsoft.OpenApi.OData.Edm
2425
/// </summary>
2526
internal class ODataContext
2627
{
27-
private IEnumerable<ODataPath> _allPaths;
28+
private IEnumerable<ODataPath>? _allPaths;
2829
private readonly IODataPathProvider _pathProvider;
2930

3031
/// <summary>
@@ -135,7 +136,7 @@ public IEnumerable<ODataPath> AllPaths
135136
/// <summary>
136137
/// Gets all tags.
137138
/// </summary>
138-
public ISet<OpenApiTag> Tags { get; private set; }
139+
public ISet<OpenApiTag>? Tags { get; private set; }
139140

140141
/// <summary>
141142
/// Append tag.
@@ -145,7 +146,7 @@ internal void AppendTag(OpenApiTag tagItem)
145146
{
146147
Tags ??= new HashSet<OpenApiTag>();
147148

148-
if (FindTagByName(tagItem.Name) is not null)
149+
if (tagItem.Name is not null && FindTagByName(tagItem.Name) is not null)
149150
{
150151
return;
151152
}
@@ -158,7 +159,7 @@ internal void AppendTag(OpenApiTag tagItem)
158159
/// </summary>
159160
/// <param name="name">The name to lookup the tag.</param>
160161
/// <returns></returns>
161-
internal OpenApiTag FindTagByName(string name)
162+
internal OpenApiTag? FindTagByName(string name)
162163
{
163164
Utils.CheckArgumentNullOrEmpty(name, nameof(name));
164165
return Tags?.FirstOrDefault(t => StringComparer.Ordinal.Equals(t.Name, name));
@@ -180,11 +181,13 @@ internal void AddExtensionToTag(string tagName, string extensionName, OpenApiAny
180181

181182
if (FindTagByName(tagName) is {} foundTag)
182183
{
184+
foundTag.Extensions ??= new Dictionary<string, IOpenApiExtension>();
183185
foundTag.Extensions.TryAdd(extensionName, extensionValue);
184186
}
185187
else
186188
{
187189
var tag = initialValueFactory();
190+
tag.Extensions ??= new Dictionary<string, IOpenApiExtension>();
188191
tag.Extensions.TryAdd(extensionName, extensionValue);
189192
AppendTag(tag);
190193
}

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

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ private void RetrieveComplexPropertyPaths(IEdmEntityType entityType, ODataPath c
346346
// Append navigation property paths for this complex property
347347
RetrieveComplexTypeNavigationPropertyPaths(complexType, currentPath, convertSettings);
348348

349-
// Traverse this complex property to rerieve nested navigation property paths
349+
// Traverse this complex property to retrieve nested navigation property paths
350350
TraverseComplexProperty(sp, currentPath, convertSettings);
351351
}
352352

@@ -519,12 +519,11 @@ private void RetrieveNavigationPropertyPaths(
519519
}
520520

521521
// Get the annotatable navigation source for this navigation property.
522-
IEdmVocabularyAnnotatable annotatableNavigationSource = (currentPath.FirstSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
523522
NavigationRestrictionsType? navSourceRestrictionType = null;
524523
NavigationRestrictionsType? navPropRestrictionType = null;
525524

526525
// Get the NavigationRestrictions referenced by this navigation property: Can be defined in the navigation source or in-lined in the navigation property.
527-
if (annotatableNavigationSource != null && _model is not null)
526+
if (currentPath.FirstSegment is ODataNavigationSourceSegment { NavigationSource: IEdmVocabularyAnnotatable annotatableNavigationSource } && _model is not null)
528527
{
529528
navSourceRestrictionType = _model.GetRecord<NavigationRestrictionsType>(annotatableNavigationSource, CapabilitiesConstants.NavigationRestrictions);
530529
navPropRestrictionType = _model.GetRecord<NavigationRestrictionsType>(navigationProperty, CapabilitiesConstants.NavigationRestrictions);
@@ -550,22 +549,13 @@ private void RetrieveNavigationPropertyPaths(
550549
visitedNavigationProperties.Push(navPropFullyQualifiedName);
551550

552551
// For fetching annotations
553-
var targetPath = currentPath.GetTargetPath(_model);
552+
var targetPath = _model is null ? null : currentPath.GetTargetPath(_model);
554553

555554
// Check whether a collection-valued navigation property should be indexed by key value(s).
556555
// Find indexability annotation annotated directly via NavigationPropertyRestriction.
557-
bool? annotatedIndexability = _model.GetBoolean(targetPath, CapabilitiesConstants.IndexableByKey)
558-
?? _model.GetBoolean(navigationProperty, CapabilitiesConstants.IndexableByKey);
559-
bool indexableByKey = true;
560-
561-
if (restriction?.IndexableByKey != null)
562-
{
563-
indexableByKey = (bool)restriction.IndexableByKey;
564-
}
565-
else if (annotatedIndexability != null)
566-
{
567-
indexableByKey = annotatedIndexability.Value;
568-
}
556+
bool? annotatedIndexability = (string.IsNullOrEmpty(targetPath) ? null : _model?.GetBoolean(targetPath, CapabilitiesConstants.IndexableByKey))
557+
?? _model?.GetBoolean(navigationProperty, CapabilitiesConstants.IndexableByKey);
558+
bool indexableByKey = restriction?.IndexableByKey ?? annotatedIndexability ?? true;
569559

570560
if (indexableByKey)
571561
{
@@ -578,8 +568,8 @@ private void RetrieveNavigationPropertyPaths(
578568
if (count == null)
579569
{
580570
// First, get the directly annotated restriction annotation of the navigation property
581-
count = _model.GetRecord<CountRestrictionsType>(targetPath, CapabilitiesConstants.CountRestrictions)
582-
?? _model.GetRecord<CountRestrictionsType>(navigationProperty, CapabilitiesConstants.CountRestrictions);
571+
count = (string.IsNullOrEmpty(targetPath) ? null : _model?.GetRecord<CountRestrictionsType>(targetPath, CapabilitiesConstants.CountRestrictions))
572+
?? _model?.GetRecord<CountRestrictionsType>(navigationProperty, CapabilitiesConstants.CountRestrictions);
583573
createCountPath = count?.Countable;
584574
}
585575

@@ -740,8 +730,6 @@ private void CreateTypeCastPaths(ODataPath currentPath, OpenApiConvertSettings c
740730
if(!annotedTypeNames.Any() && convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments)
741731
return; // we don't want to generate any downcast path item if there is no type cast annotation.
742732

743-
var annotedTypeNamesSet = new HashSet<string>(annotedTypeNames, StringComparer.OrdinalIgnoreCase);
744-
745733
bool filter(IEdmStructuredType x) =>
746734
convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && annotedTypeNames.Contains(x.FullTypeName()) ||
747735
!convertSettings.RequireDerivedTypesConstraintForODataTypeCastSegments && (
@@ -750,16 +738,18 @@ bool filter(IEdmStructuredType x) =>
750738
);
751739

752740
var targetTypes = _model
753-
.FindAllDerivedTypes(structuredType)
741+
?.FindAllDerivedTypes(structuredType)
754742
.Where(x => (x.TypeKind == EdmTypeKind.Entity || x.TypeKind == EdmTypeKind.Complex) && filter(x))
755743
.OfType<IEdmStructuredType>()
756744
.ToArray();
757745

746+
if (targetTypes is not { Length: > 0} || _model is null) return;
747+
758748
foreach (var targetType in targetTypes)
759749
{
760750
var targetTypeSegment = new ODataTypeCastSegment(targetType, _model);
761751

762-
if (currentPath.Segments.Any(x => x.Identifier.Equals(targetTypeSegment.Identifier)))
752+
if (currentPath.Segments.Any(x => x.Identifier?.Equals(targetTypeSegment.Identifier) ?? false))
763753
{
764754
// In case we have expanded a derived type's navigation property
765755
// and we are in a cyclic loop where the expanded navigation property
@@ -802,7 +792,7 @@ bool filter(IEdmStructuredType x) =>
802792
/// </summary>
803793
private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings)
804794
{
805-
var edmOperations = _model.GetAllElements().OfType<IEdmOperation>().Where(x => x.IsBound).ToArray();
795+
var edmOperations = _model?.GetAllElements().OfType<IEdmOperation>().Where(x => x.IsBound).ToArray() ?? [];
806796
foreach (var edmOperation in edmOperations)
807797
{
808798
if (!CanFilter(edmOperation))
@@ -876,7 +866,7 @@ private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings)
876866
&& operationSegment.Operation is IEdmFunction edmFunction
877867
&& edmFunction.IsComposable
878868
&& edmFunction.ReturnType != null
879-
&& edmFunction.ReturnType.Definition is IEdmEntityType returnBindingEntityType);
869+
&& edmFunction.ReturnType.Definition is IEdmEntityType);
880870

881871
foreach( var functionPath in functionPaths)
882872
{
@@ -902,11 +892,11 @@ functionPath.LastSegment is ODataOperationSegment &&
902892
{
903893
/* Get number of segments already appended after the first composable function segment
904894
*/
905-
int composableFuncSegIndex = functionPath.Segments.IndexOf(
906-
functionPath.Segments.FirstOrDefault(
907-
x => x is ODataOperationSegment operationSegment &&
908-
operationSegment.Operation is IEdmFunction edmFunction &&
909-
edmFunction.IsComposable));
895+
int composableFuncSegIndex = functionPath
896+
.Segments
897+
.OfType<ODataOperationSegment>()
898+
.FirstOrDefault(x => x.Operation is IEdmFunction {IsComposable: true}) is {} firstOperationSegment ?
899+
functionPath.Segments.IndexOf(firstOperationSegment) : -1;
910900
int currentDepth = functionPath.Count - composableFuncSegIndex - 1;
911901

912902
if (currentDepth < convertSettings.ComposableFunctionsExpansionDepth)
@@ -928,10 +918,10 @@ bool filter(IEdmNavigationSource z) =>
928918
z.EntityType.FindAllBaseTypes().Contains(firstEntityType);
929919

930920
return new IEdmEntityType[] { firstEntityType }
931-
.Union(_model.EntityContainer.EntitySets()
932-
.Where(filter).Select(x => x.EntityType)) //Search all EntitySets
933-
.Union(_model.EntityContainer.Singletons()
934-
.Where(filter).Select(x => x.EntityType)) //Search all singletons
921+
.Union(_model?.EntityContainer.EntitySets()
922+
.Where(filter).Select(x => x.EntityType) ?? []) //Search all EntitySets
923+
.Union(_model?.EntityContainer.Singletons()
924+
.Where(filter).Select(x => x.EntityType) ?? []) //Search all singletons
935925
.Distinct()
936926
.ToList();
937927
}
@@ -944,9 +934,9 @@ bool filter(IEdmNavigationSource z) =>
944934
};
945935
private void AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType, OpenApiConvertSettings convertSettings)
946936
{
947-
if (_allNavigationSourcePaths.TryGetValue(bindingEntityType, out IList<ODataPath> value))
937+
if (_allNavigationSourcePaths.TryGetValue(bindingEntityType, out var value))
948938
{
949-
bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
939+
bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
950940

951941
foreach (var subPath in value)
952942
{
@@ -973,7 +963,7 @@ secondLastPathSegment is not ODataKeySegment &&
973963
var annotatable = (lastPathSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
974964
annotatable ??= (lastPathSegment as ODataKeySegment)?.EntityType;
975965

976-
if (annotatable != null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, annotatable))
966+
if (annotatable != null && _model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, annotatable))
977967
{
978968
// Check whether the navigation source is allowed to have an operation on the entity type
979969
annotatable = (secondLastPathSegment as ODataNavigationSourceSegment)?.NavigationSource as IEdmVocabularyAnnotatable;
@@ -983,9 +973,12 @@ secondLastPathSegment is not ODataKeySegment &&
983973
}
984974
}
985975

986-
ODataPath newPath = subPath.Clone();
987-
newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
988-
AppendPath(newPath);
976+
if (_model is not null)
977+
{
978+
ODataPath newPath = subPath.Clone();
979+
newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
980+
AppendPath(newPath);
981+
}
989982
}
990983
}
991984
}
@@ -995,15 +988,15 @@ secondLastPathSegment is not ODataKeySegment &&
995988
};
996989
private void AppendBoundOperationOnNavigationPropertyPath(IEdmOperation edmOperation, bool isCollection, IEdmEntityType bindingEntityType)
997990
{
998-
bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
991+
bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
999992

1000-
if (_allNavigationPropertyPaths.TryGetValue(bindingEntityType, out IList<ODataPath> value))
993+
if (_allNavigationPropertyPaths.TryGetValue(bindingEntityType, out var value))
1001994
{
1002995
foreach (var path in value.Where(x => !_pathKindToSkipForNavigationProperties.Contains(x.Kind)))
1003996
{
1004-
ODataNavigationPropertySegment npSegment = path.Segments.Last(s => s is ODataNavigationPropertySegment) as ODataNavigationPropertySegment;
997+
ODataNavigationPropertySegment npSegment = path.Segments.OfType<ODataNavigationPropertySegment>().Last();
1005998

1006-
if (!EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
999+
if (_model is not null && !EdmModelHelper.IsOperationAllowed(_model, edmOperation, npSegment.NavigationProperty, npSegment.NavigationProperty.ContainsTarget))
10071000
{
10081001
continue;
10091002
}
@@ -1030,9 +1023,12 @@ private void AppendBoundOperationOnNavigationPropertyPath(IEdmOperation edmOpera
10301023
}
10311024
}
10321025

1033-
ODataPath newPath = path.Clone();
1034-
newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
1035-
AppendPath(newPath);
1026+
if (_model is not null)
1027+
{
1028+
ODataPath newPath = path.Clone();
1029+
newPath.Push(new ODataOperationSegment(edmOperation, isEscapedFunction, _model));
1030+
AppendPath(newPath);
1031+
}
10361032
}
10371033
}
10381034
}
@@ -1044,22 +1040,24 @@ private void AppendBoundOperationOnDerived(
10441040
OpenApiConvertSettings convertSettings)
10451041
{
10461042
if (!convertSettings.AppendBoundOperationsOnDerivedTypeCastSegments) return;
1047-
bool isEscapedFunction = _model.IsUrlEscapeFunction(edmOperation);
1043+
bool isEscapedFunction = _model?.IsUrlEscapeFunction(edmOperation) ?? false;
1044+
if (_allNavigationSources is null) return;
10481045
foreach (var baseType in bindingEntityType.FindAllBaseTypes())
10491046
{
1050-
if (_allNavigationSources.TryGetValue(baseType, out IList<IEdmNavigationSource> baseNavigationSource))
1047+
if (_allNavigationSources.TryGetValue(baseType, out var baseNavigationSource))
10511048
{
10521049
foreach (var ns in baseNavigationSource)
10531050
{
1054-
if (HasUnsatisfiedDerivedTypeConstraint(
1055-
ns as IEdmVocabularyAnnotatable,
1051+
if (ns is not IEdmVocabularyAnnotatable nsAnnotable ||
1052+
HasUnsatisfiedDerivedTypeConstraint(
1053+
nsAnnotable,
10561054
baseType,
10571055
convertSettings))
10581056
{
10591057
continue;
10601058
}
10611059

1062-
if (!EdmModelHelper.IsOperationAllowed(_model, edmOperation, ns as IEdmVocabularyAnnotatable))
1060+
if (_model is null || !EdmModelHelper.IsOperationAllowed(_model, edmOperation, nsAnnotable))
10631061
{
10641062
continue;
10651063
}

0 commit comments

Comments
 (0)