Skip to content

Commit 202fbe1

Browse files
committed
Resolver resolving
1 parent 9fc3ed3 commit 202fbe1

20 files changed

+659
-193
lines changed

src/Microsoft.OpenApi.Readers/OpenApiReaderSettings.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,35 @@
1010

1111
namespace Microsoft.OpenApi.Readers
1212
{
13+
/// <summary>
14+
/// Indicates if and when the reader should convert unresolved references into resolved objects
15+
/// </summary>
16+
public enum ReferenceResolutionSetting
17+
{
18+
/// <summary>
19+
/// Create placeholder objects with an OpenApiReference instance and UnresolvedReference set to true.
20+
/// </summary>
21+
DoNotResolveReferences,
22+
/// <summary>
23+
/// Convert local references to references of valid domain objects.
24+
/// </summary>
25+
ResolveLocalReferences,
26+
/// <summary>
27+
/// Convert all references to references of valid domain objects.
28+
/// </summary>
29+
ResolveRemoteReferences
30+
}
31+
1332
/// <summary>
1433
/// Configuration settings to control how OpenAPI documents are parsed
1534
/// </summary>
1635
public class OpenApiReaderSettings
1736
{
37+
/// <summary>
38+
/// Indicates how references in the source document should be handled.
39+
/// </summary>
40+
public ReferenceResolutionSetting ReferenceResolution { get; set; } = ReferenceResolutionSetting.ResolveRemoteReferences;
41+
1842
/// <summary>
1943
/// Dictionary of parsers for converting extensions into strongly typed classes
2044
/// </summary>

src/Microsoft.OpenApi.Readers/OpenApiStreamReader.cs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,19 @@ public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
6060
// Parse the OpenAPI Document
6161
var document = context.Parse(yamlDocument, diagnostic);
6262

63-
// Resolve References
64-
var resolver = new Resolver(document);
65-
var walker = new OpenApiWalker(resolver);
66-
walker.Walk(document);
63+
// Resolve References if requested
64+
switch (_settings.ReferenceResolution)
65+
{
66+
case ReferenceResolutionSetting.ResolveRemoteReferences:
67+
case ReferenceResolutionSetting.ResolveLocalReferences:
68+
var resolver = new OpenApiReferenceResolver(document);
69+
var walker = new OpenApiWalker(resolver);
70+
walker.Walk(document);
71+
break;
72+
case
73+
ReferenceResolutionSetting.DoNotResolveReferences:
74+
break;
75+
}
6776

6877
// Validate the document
6978
var errors = document.Validate(_settings.RuleSet);

src/Microsoft.OpenApi.Readers/ParseNodes/ListNode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using System.Linq;
88
using Microsoft.OpenApi.Any;
99
using Microsoft.OpenApi.Exceptions;
10+
using Microsoft.OpenApi.Interfaces;
11+
using Microsoft.OpenApi.Models;
1012
using SharpYaml.Serialization;
1113

1214
namespace Microsoft.OpenApi.Readers.ParseNodes
@@ -36,6 +38,7 @@ public override List<T> CreateList<T>(Func<MapNode, T> map)
3638
.ToList();
3739
}
3840

41+
3942
public override List<T> CreateSimpleList<T>(Func<ValueNode, T> map)
4043
{
4144
var yamlSequence = _nodeList;

src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,34 @@ public override Dictionary<string, T> CreateMap<T>(Func<MapNode, T> map)
7878
return nodes.ToDictionary(k => k.key, v => v.value);
7979
}
8080

81-
// public override Dictionary<string, T> CreateMapWithReference<T>(
82-
// ReferenceType referenceType,
83-
// string refpointerbase,
84-
// Func<MapNode, T> map)
85-
// {
86-
// var yamlMap = _node;
87-
// if (yamlMap == null)
88-
// {
89-
// throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
90-
// }
91-
92-
// var nodes = yamlMap.Select(
93-
// n => new
94-
// {
95-
// key = n.Key.GetScalarValue(),
96-
// value = GetReferencedObject<T>(referenceType, refpointerbase + n.Key.GetScalarValue()) ??
97-
// map(new MapNode(Context, Diagnostic, (YamlMappingNode)n.Value))
98-
// });
99-
// return nodes.ToDictionary(k => k.key, v => v.value);
100-
// }
81+
public override Dictionary<string, T> CreateMapWithReference<T>(
82+
ReferenceType referenceType,
83+
string refpointerbase,
84+
Func<MapNode, T> map)
85+
{
86+
var yamlMap = _node;
87+
if (yamlMap == null)
88+
{
89+
throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
90+
}
91+
92+
var nodes = yamlMap.Select(
93+
n => {
94+
var entry = new
95+
{
96+
key = n.Key.GetScalarValue(),
97+
value = map(new MapNode(Context, Diagnostic, (YamlMappingNode)n.Value))
98+
};
99+
entry.value.Reference = new OpenApiReference()
100+
{
101+
Type = referenceType,
102+
Id = entry.key
103+
};
104+
return entry;
105+
}
106+
);
107+
return nodes.ToDictionary(k => k.key, v => v.value);
108+
}
101109

102110
public override Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
103111
{

src/Microsoft.OpenApi.Readers/ParsingContext.cs

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ namespace Microsoft.OpenApi.Readers
2222
public class ParsingContext
2323
{
2424
private readonly Stack<string> _currentLocation = new Stack<string>();
25-
private readonly Dictionary<string, IOpenApiReferenceable> _referenceStore = new Dictionary<string, IOpenApiReferenceable>();
25+
2626
private readonly Dictionary<string, object> _tempStorage = new Dictionary<string, object>();
2727
private IOpenApiVersionService _versionService;
2828
private readonly Dictionary<string, Stack<string>> _loopStacks = new Dictionary<string, Stack<string>>();
2929
internal Dictionary<string, Func<IOpenApiAny, IOpenApiExtension>> ExtensionParsers { get; set; } = new Dictionary<string, Func<IOpenApiAny, IOpenApiExtension>>();
3030
internal RootNode RootNode { get; set; }
3131
internal List<OpenApiTag> Tags { get; private set; } = new List<OpenApiTag>();
3232

33+
3334
/// <summary>
3435
/// Initiates the parsing process. Not thread safe and should only be called once on a parsing context
3536
/// </summary>
@@ -129,48 +130,6 @@ public string GetLocation()
129130
return "#/" + string.Join("/", _currentLocation.Reverse().ToArray());
130131
}
131132

132-
/// <summary>
133-
/// Gets the referenced object.
134-
/// </summary>
135-
public IOpenApiReferenceable GetReferencedObject(
136-
OpenApiDiagnostic diagnostic,
137-
ReferenceType referenceType,
138-
string referenceString)
139-
{
140-
_referenceStore.TryGetValue(referenceString, out var referencedObject);
141-
142-
// If reference has already been accessed once, simply return the same reference object.
143-
if (referencedObject != null)
144-
{
145-
return referencedObject;
146-
}
147-
148-
var reference = VersionService.ConvertToOpenApiReference(referenceString, referenceType);
149-
150-
var isReferencedObjectFound = VersionService.TryLoadReference(this, reference, out referencedObject);
151-
152-
if (isReferencedObjectFound)
153-
{
154-
// Populate the Reference section of the object, so that the writers
155-
// can recognize that this is referencing another object.
156-
referencedObject.Reference = reference;
157-
_referenceStore.Add(referenceString, referencedObject);
158-
}
159-
else if (referencedObject != null)
160-
{
161-
return referencedObject;
162-
}
163-
else
164-
{
165-
diagnostic.Errors.Add(
166-
new OpenApiError(
167-
GetLocation(),
168-
$"Cannot resolve the reference {referenceString}"));
169-
}
170-
171-
return referencedObject;
172-
}
173-
174133
/// <summary>
175134
/// Gets the value from the temporary storage matching the given key.
176135
/// </summary>

0 commit comments

Comments
 (0)