Skip to content

Commit 415c959

Browse files
committed
Merge branch 'vnext' into feature/ci-cd
2 parents a956d83 + 8f0de0d commit 415c959

File tree

8 files changed

+91
-41
lines changed

8 files changed

+91
-41
lines changed

src/Microsoft.OpenApi.Readers/Exceptions/OpenApiReaderException.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ public OpenApiReaderException() { }
2424
/// <param name="message">Plain text error message for this exception.</param>
2525
public OpenApiReaderException(string message) : base(message) { }
2626

27+
/// <summary>
28+
/// Initializes the <see cref="OpenApiReaderException"/> class with a custom message.
29+
/// </summary>
30+
/// <param name="message">Plain text error message for this exception.</param>
31+
/// <param name="context">Context of current parsing process.</param>
32+
public OpenApiReaderException(string message, ParsingContext context) : base(message) {
33+
Pointer = context.GetLocation();
34+
}
35+
2736
/// <summary>
2837
/// Initializes the <see cref="OpenApiReaderException"/> class with a message and line, column location of error.
2938
/// </summary>
@@ -42,5 +51,6 @@ public OpenApiReaderException(string message, YamlNode node) : base(message)
4251
/// <param name="message">Plain text error message for this exception.</param>
4352
/// <param name="innerException">Inner exception that caused this exception to be thrown.</param>
4453
public OpenApiReaderException(string message, Exception innerException) : base(message, innerException) { }
54+
4555
}
4656
}

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
using System.Collections.Generic;
77
using System.Linq;
88
using Microsoft.OpenApi.Any;
9-
using Microsoft.OpenApi.Exceptions;
10-
using Microsoft.OpenApi.Interfaces;
11-
using Microsoft.OpenApi.Models;
9+
using Microsoft.OpenApi.Readers.Exceptions;
1210
using SharpYaml.Serialization;
1311

1412
namespace Microsoft.OpenApi.Readers.ParseNodes
@@ -27,8 +25,8 @@ public override List<T> CreateList<T>(Func<MapNode, T> map)
2725
{
2826
if (_nodeList == null)
2927
{
30-
throw new OpenApiException(
31-
$"Expected list at line {_nodeList.Start.Line} while parsing {typeof(T).Name}");
28+
throw new OpenApiReaderException(
29+
$"Expected list at line {_nodeList.Start.Line} while parsing {typeof(T).Name}", _nodeList);
3230
}
3331

3432
return _nodeList.Select(n => map(new MapNode(Context, n as YamlMappingNode)))
@@ -47,8 +45,8 @@ public override List<T> CreateSimpleList<T>(Func<ValueNode, T> map)
4745
{
4846
if (_nodeList == null)
4947
{
50-
throw new OpenApiException(
51-
$"Expected list at line {_nodeList.Start.Line} while parsing {typeof(T).Name}");
48+
throw new OpenApiReaderException(
49+
$"Expected list at line {_nodeList.Start.Line} while parsing {typeof(T).Name}", _nodeList);
5250
}
5351

5452
return _nodeList.Select(n => map(new ValueNode(Context, n))).ToList();

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

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Collections.Generic;
77
using System.Linq;
88
using Microsoft.OpenApi.Any;
9-
using Microsoft.OpenApi.Exceptions;
109
using Microsoft.OpenApi.Interfaces;
1110
using Microsoft.OpenApi.Models;
1211
using Microsoft.OpenApi.Readers.Exceptions;
@@ -33,7 +32,7 @@ public MapNode(ParsingContext context, YamlNode node) : base(
3332
{
3433
if (!(node is YamlMappingNode mapNode))
3534
{
36-
throw new OpenApiReaderException("Expected map.", node);
35+
throw new OpenApiReaderException("Expected map.", Context);
3736
}
3837

3938
this._node = mapNode;
@@ -48,10 +47,10 @@ public PropertyNode this[string key]
4847
{
4948
get
5049
{
51-
YamlNode node = null;
50+
YamlNode node;
5251
if (this._node.Children.TryGetValue(new YamlScalarNode(key), out node))
5352
{
54-
return new PropertyNode(Context, key, this._node.Children[new YamlScalarNode(key)]);
53+
return new PropertyNode(Context, key, node);
5554
}
5655

5756
return null;
@@ -63,16 +62,30 @@ public override Dictionary<string, T> CreateMap<T>(Func<MapNode, T> map)
6362
var yamlMap = _node;
6463
if (yamlMap == null)
6564
{
66-
throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
65+
throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
6766
}
6867

6968
var nodes = yamlMap.Select(
70-
n => new
71-
{
72-
key = n.Key.GetScalarValue(),
73-
value = n.Value as YamlMappingNode == null
74-
? default(T)
75-
: map(new MapNode(Context, n.Value as YamlMappingNode))
69+
n => {
70+
71+
var key = n.Key.GetScalarValue();
72+
T value;
73+
try
74+
{
75+
Context.StartObject(key);
76+
value = n.Value as YamlMappingNode == null
77+
? default(T)
78+
: map(new MapNode(Context, n.Value as YamlMappingNode));
79+
}
80+
finally
81+
{
82+
Context.EndObject();
83+
}
84+
return new
85+
{
86+
key = key,
87+
value = value
88+
};
7689
});
7790

7891
return nodes.ToDictionary(k => k.key, v => v.value);
@@ -85,7 +98,7 @@ public override Dictionary<string, T> CreateMapWithReference<T>(
8598
var yamlMap = _node;
8699
if (yamlMap == null)
87100
{
88-
throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
101+
throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
89102
}
90103

91104
var nodes = yamlMap.Select(
@@ -119,8 +132,8 @@ public override Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
119132
{
120133
var yamlMap = _node;
121134
if (yamlMap == null)
122-
{
123-
throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
135+
{
136+
throw new OpenApiReaderException($"Expected map while parsing {typeof(T).Name}", Context);
124137
}
125138

126139
var nodes = yamlMap.Select(
@@ -175,7 +188,7 @@ public string GetScalarValue(ValueNode key)
175188
var scalarNode = _node.Children[new YamlScalarNode(key.GetScalarValue())] as YamlScalarNode;
176189
if (scalarNode == null)
177190
{
178-
throw new OpenApiException($"Expected scalar at line {_node.Start.Line} for key {key.GetScalarValue()}");
191+
throw new OpenApiReaderException($"Expected scalar at line {_node.Start.Line} for key {key.GetScalarValue()}", Context);
179192
}
180193

181194
return scalarNode.Value;

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public MapNode CheckMapNode(string nodeName)
2626
{
2727
if (!(this is MapNode mapNode))
2828
{
29-
throw new OpenApiReaderException($"{nodeName} must be a map/object");
29+
throw new OpenApiReaderException($"{nodeName} must be a map/object", Context);
3030
}
3131

3232
return mapNode;
@@ -50,51 +50,50 @@ public static ParseNode Create(ParsingContext context, YamlNode node)
5050

5151
public virtual List<T> CreateList<T>(Func<MapNode, T> map)
5252
{
53-
throw new OpenApiReaderException("Cannot create list from this type of node.");
53+
throw new OpenApiReaderException("Cannot create list from this type of node.", Context);
5454
}
5555

5656
public virtual Dictionary<string, T> CreateMap<T>(Func<MapNode, T> map)
5757
{
58-
throw new OpenApiReaderException("Cannot create map from this type of node.");
58+
throw new OpenApiReaderException("Cannot create map from this type of node.", Context);
5959
}
6060

6161
public virtual Dictionary<string, T> CreateMapWithReference<T>(
6262
ReferenceType referenceType,
6363
Func<MapNode, T> map)
6464
where T : class, IOpenApiReferenceable
6565
{
66-
throw new OpenApiReaderException("Cannot create map from this reference.");
66+
throw new OpenApiReaderException("Cannot create map from this reference.", Context);
6767
}
6868

6969
public virtual List<T> CreateSimpleList<T>(Func<ValueNode, T> map)
7070
{
71-
throw new OpenApiReaderException("Cannot create simple list from this type of node.");
71+
throw new OpenApiReaderException("Cannot create simple list from this type of node.", Context);
7272
}
7373

7474
public virtual Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
7575
{
76-
throw new OpenApiReaderException("Cannot create simple map from this type of node.");
76+
throw new OpenApiReaderException("Cannot create simple map from this type of node.", Context);
7777
}
7878

7979
public virtual IOpenApiAny CreateAny()
8080
{
81-
throw new OpenApiReaderException("Cannot create an Any object this type of node.");
81+
throw new OpenApiReaderException("Cannot create an Any object this type of node.", Context);
8282
}
8383

8484
public virtual string GetRaw()
8585
{
86-
throw new OpenApiReaderException("Cannot get raw value from this type of node.");
86+
throw new OpenApiReaderException("Cannot get raw value from this type of node.", Context);
8787
}
8888

8989
public virtual string GetScalarValue()
9090
{
91-
throw new OpenApiReaderException("Cannot create a scalar value from this type of node.");
91+
throw new OpenApiReaderException("Cannot create a scalar value from this type of node.", Context);
9292
}
9393

9494
public virtual List<IOpenApiAny> CreateListOfAny()
9595
{
96-
throw new OpenApiReaderException("Cannot create a list from this type of node.");
96+
throw new OpenApiReaderException("Cannot create a list from this type of node.", Context);
9797
}
98-
9998
}
10099
}

src/Microsoft.OpenApi.Readers/ParsingContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public void EndObject()
141141
/// </summary>
142142
public string GetLocation()
143143
{
144-
return "#/" + string.Join("/", _currentLocation.Reverse().ToArray());
144+
return "#/" + string.Join("/", _currentLocation.Reverse().Select(s=> s.Replace("~","~0").Replace("/","~1")).ToArray());
145145
}
146146

147147
/// <summary>

src/Microsoft.OpenApi/Exceptions/OpenApiException.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,14 @@ public OpenApiException(string message, Exception innerException)
3939
}
4040

4141
/// <summary>
42-
/// The reference pointer.
42+
/// The reference pointer. This is a fragment identifier used to point to where the error occurred in the document.
43+
/// If the document has been parsed as JSON/YAML then the identifier will be a
44+
/// JSON Pointer as per https://tools.ietf.org/html/rfc6901
45+
/// If the document fails to parse as JSON/YAML then the fragment will be based on
46+
/// a text/plain pointer as defined in https://tools.ietf.org/html/rfc5147
47+
/// Currently only line= is provided because using char= causes tests to break due to CR/LF and LF differences
4348
/// </summary>
4449
public string Pointer { get; set; }
50+
4551
}
4652
}

test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,7 @@
261261
<ProjectReference Include="..\..\src\Microsoft.OpenApi\Microsoft.OpenApi.csproj" />
262262
<ProjectReference Include="..\..\src\Microsoft.OpenApi.Readers\Microsoft.OpenApi.Readers.csproj" />
263263
</ItemGroup>
264-
265-
<ItemGroup>
266-
<Reference Include="Microsoft.CSharp" />
267-
<Reference Include="System.Net.Http" />
268-
</ItemGroup>
269-
264+
270265
<ItemGroup>
271266
<None Update="V2Tests\Samples\definitions.v3.yaml">
272267
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,34 @@ public void BrokenSimpleList()
3131
})
3232
});
3333
}
34+
35+
[Fact]
36+
public void BadSchema()
37+
{
38+
var input = @"openapi: 3.0.0
39+
info:
40+
title: foo
41+
version: bar
42+
paths:
43+
'/foo':
44+
get:
45+
responses:
46+
200:
47+
description: ok
48+
content:
49+
application/json:
50+
schema: asdasd
51+
";
52+
53+
var reader = new OpenApiStringReader();
54+
reader.Read(input, out var diagnostic);
55+
56+
diagnostic.Errors.Should().BeEquivalentTo(new List<OpenApiError>() {
57+
new OpenApiError(new OpenApiReaderException("schema must be a map/object") {
58+
Pointer = "#/paths/~1foo/get/responses/200/content/application~1json/schema"
59+
})
60+
});
61+
}
3462
}
3563
}
64+

0 commit comments

Comments
 (0)