forked from microsoft/OpenAPI.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenApiDocumentRules.cs
More file actions
103 lines (93 loc) · 3.56 KB
/
OpenApiDocumentRules.cs
File metadata and controls
103 lines (93 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System;
namespace Microsoft.OpenApi
{
/// <summary>
/// The validation rules for <see cref="OpenApiDocument"/>.
/// </summary>
[OpenApiRule]
public static class OpenApiDocumentRules
{
/// <summary>
/// The Info field is required.
/// </summary>
public static ValidationRule<OpenApiDocument> OpenApiDocumentFieldIsMissing =>
new(nameof(OpenApiDocumentFieldIsMissing),
(context, item) =>
{
// info
if (item.Info == null)
{
context.Enter("info");
context.CreateError(nameof(OpenApiDocumentFieldIsMissing),
string.Format(SRResource.Validation_FieldIsRequired, "info", "document"));
context.Exit();
}
});
/// <summary>
/// All references in the OpenAPI document must be valid.
/// </summary>
public static ValidationRule<OpenApiDocument> OpenApiDocumentReferencesAreValid =>
new(nameof(OpenApiDocumentReferencesAreValid),
static (context, item) =>
{
const string RuleName = nameof(OpenApiDocumentReferencesAreValid);
var visitor = new OpenApiSchemaReferenceVisitor(RuleName, context);
var walker = new OpenApiWalker(visitor);
walker.Walk(item);
});
private sealed class OpenApiSchemaReferenceVisitor(
string ruleName,
IValidationContext context) : OpenApiVisitorBase
{
public override void Visit(IOpenApiReferenceHolder referenceHolder)
{
if (referenceHolder is OpenApiSchemaReference reference)
{
ValidateSchemaReference(reference);
}
}
public override void Visit(IOpenApiSchema schema)
{
if (schema is OpenApiSchemaReference reference)
{
ValidateSchemaReference(reference);
}
}
private void ValidateSchemaReference(OpenApiSchemaReference reference)
{
if (!reference.Reference.IsLocal)
{
return;
}
try
{
if (reference.RecursiveTarget is null)
{
// The reference was not followed to a valid schema somewhere in the document
context.Enter(GetSegment());
context.CreateWarning(ruleName, string.Format(SRResource.Validation_SchemaReferenceDoesNotExist, reference.Reference.ReferenceV3));
context.Exit();
}
}
catch (InvalidOperationException ex)
{
context.Enter(GetSegment());
context.CreateWarning(ruleName, ex.Message);
context.Exit();
}
string GetSegment()
{
// Trim off the leading "#/" as the context is already at the root of the document
return
#if NET8_0_OR_GREATER
$"{PathString[2..]}/$ref";
#else
PathString.Substring(2) + "/$ref";
#endif
}
}
}
}
}