Skip to content

Commit 02eeec1

Browse files
Merge branch 'vnext' into mk/add-cmdtool-build-task
2 parents d1a13a5 + 9f46c00 commit 02eeec1

File tree

12 files changed

+1222
-73
lines changed

12 files changed

+1222
-73
lines changed

src/Microsoft.OpenApi.Tool/OpenApiService.cs

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System;
2-
using System.Collections.Generic;
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System;
35
using System.IO;
46
using System.Linq;
57
using System.Net;
@@ -21,29 +23,44 @@ public static void ProcessOpenApiDocument(
2123
FileInfo output,
2224
OpenApiSpecVersion version,
2325
OpenApiFormat format,
26+
string filterByOperationIds,
2427
bool inline,
2528
bool resolveExternal)
2629
{
27-
if (input == null)
30+
if (string.IsNullOrEmpty(input))
2831
{
29-
throw new ArgumentNullException("input");
32+
throw new ArgumentNullException(nameof(input));
33+
}
34+
if(output == null)
35+
{
36+
throw new ArgumentException(nameof(output));
37+
}
38+
if (output.Exists)
39+
{
40+
throw new IOException("The file you're writing to already exists. Please input a new output path.");
3041
}
3142

3243
var stream = GetStream(input);
33-
34-
OpenApiDocument document;
35-
3644
var result = new OpenApiStreamReader(new OpenApiReaderSettings
3745
{
38-
ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
46+
ReferenceResolution = resolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
3947
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
4048
}
4149
).ReadAsync(stream).GetAwaiter().GetResult();
4250

51+
OpenApiDocument document;
4352
document = result.OpenApiDocument;
53+
54+
// Check if filter options are provided, then execute
55+
if (!string.IsNullOrEmpty(filterByOperationIds))
56+
{
57+
var predicate = OpenApiFilterService.CreatePredicate(filterByOperationIds);
58+
document = OpenApiFilterService.CreateFilteredDocument(document, predicate);
59+
}
60+
4461
var context = result.OpenApiDiagnostic;
4562

46-
if (context.Errors.Count != 0)
63+
if (context.Errors.Count > 0)
4764
{
4865
var errorReport = new StringBuilder();
4966

@@ -52,43 +69,26 @@ public static void ProcessOpenApiDocument(
5269
errorReport.AppendLine(error.ToString());
5370
}
5471

55-
throw new ArgumentException(String.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray()));
72+
throw new ArgumentException(string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray()));
5673
}
5774

58-
using (var outputStream = output?.Create())
59-
{
60-
TextWriter textWriter;
61-
62-
if (outputStream != null)
63-
{
64-
textWriter = new StreamWriter(outputStream);
65-
}
66-
else
67-
{
68-
textWriter = Console.Out;
69-
}
75+
using var outputStream = output?.Create();
7076

71-
var settings = new OpenApiWriterSettings()
72-
{
73-
ReferenceInline = inline == true ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences
74-
};
75-
IOpenApiWriter writer;
76-
switch (format)
77-
{
78-
case OpenApiFormat.Json:
79-
writer = new OpenApiJsonWriter(textWriter, settings);
80-
break;
81-
case OpenApiFormat.Yaml:
82-
writer = new OpenApiYamlWriter(textWriter, settings);
83-
break;
84-
default:
85-
throw new ArgumentException("Unknown format");
86-
}
77+
var textWriter = outputStream != null ? new StreamWriter(outputStream) : Console.Out;
8778

88-
document.Serialize(writer, version);
79+
var settings = new OpenApiWriterSettings()
80+
{
81+
ReferenceInline = inline ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences
82+
};
83+
IOpenApiWriter writer = format switch
84+
{
85+
OpenApiFormat.Json => new OpenApiJsonWriter(textWriter, settings),
86+
OpenApiFormat.Yaml => new OpenApiYamlWriter(textWriter, settings),
87+
_ => throw new ArgumentException("Unknown format"),
88+
};
89+
document.Serialize(writer, version);
8990

90-
textWriter.Flush();
91-
}
91+
textWriter.Flush();
9292
}
9393

9494
private static Stream GetStream(string input)
@@ -127,7 +127,6 @@ internal static void ValidateOpenApiDocument(string input)
127127

128128
document = new OpenApiStreamReader(new OpenApiReaderSettings
129129
{
130-
//ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
131130
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
132131
}
133132
).Read(stream, out var context);

src/Microsoft.OpenApi.Tool/Program.cs

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,15 @@
1-
using System;
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
24
using System.CommandLine;
35
using System.CommandLine.Invocation;
46
using System.IO;
57
using System.Threading.Tasks;
6-
using Microsoft.OpenApi;
78

89
namespace Microsoft.OpenApi.Tool
910
{
10-
class Program
11+
static class Program
1112
{
12-
static async Task<int> OldMain(string[] args)
13-
{
14-
15-
var command = new RootCommand
16-
{
17-
new Option("--input", "Input OpenAPI description file path or URL", typeof(string) ),
18-
new Option("--output","Output OpenAPI description file", typeof(FileInfo), arity: ArgumentArity.ZeroOrOne),
19-
new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)),
20-
new Option("--format", "File format",typeof(OpenApiFormat) ),
21-
new Option("--inline", "Inline $ref instances", typeof(bool) ),
22-
new Option("--resolveExternal","Resolve external $refs", typeof(bool))
23-
};
24-
25-
command.Handler = CommandHandler.Create<string,FileInfo,OpenApiSpecVersion,OpenApiFormat,bool, bool>(
26-
OpenApiService.ProcessOpenApiDocument);
27-
28-
// Parse the incoming args and invoke the handler
29-
return await command.InvokeAsync(args);
30-
}
31-
3213
static async Task<int> Main(string[] args)
3314
{
3415
var rootCommand = new RootCommand() {
@@ -47,9 +28,10 @@ static async Task<int> Main(string[] args)
4728
new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)),
4829
new Option("--format", "File format",typeof(OpenApiFormat) ),
4930
new Option("--inline", "Inline $ref instances", typeof(bool) ),
50-
new Option("--resolveExternal","Resolve external $refs", typeof(bool))
31+
new Option("--resolveExternal","Resolve external $refs", typeof(bool)),
32+
new Option("--filterByOperationIds", "Filters by OperationId provided", typeof(string))
5133
};
52-
transformCommand.Handler = CommandHandler.Create<string, FileInfo, OpenApiSpecVersion, OpenApiFormat, bool, bool>(
34+
transformCommand.Handler = CommandHandler.Create<string, FileInfo, OpenApiSpecVersion, OpenApiFormat, string, bool, bool>(
5335
OpenApiService.ProcessOpenApiDocument);
5436

5537
rootCommand.Add(transformCommand);

src/Microsoft.OpenApi/Microsoft.OpenApi.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>netstandard2.0</TargetFrameworks>
4+
<LangVersion>9.0</LangVersion>
45
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
56
<PackageIconUrl>http://go.microsoft.com/fwlink/?LinkID=288890</PackageIconUrl>
67
<PackageProjectUrl>https://github.com/Microsoft/OpenAPI.NET</PackageProjectUrl>
@@ -36,7 +37,7 @@
3637
</PropertyGroup>
3738

3839
<ItemGroup>
39-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
40+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
4041
</ItemGroup>
4142

4243
<ItemGroup>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using Microsoft.OpenApi.Interfaces;
6+
using Microsoft.OpenApi.Models;
7+
8+
namespace Microsoft.OpenApi.Services
9+
{
10+
internal class CopyReferences : OpenApiVisitorBase
11+
{
12+
private readonly OpenApiDocument _target;
13+
public OpenApiComponents Components = new();
14+
15+
public CopyReferences(OpenApiDocument target)
16+
{
17+
_target = target;
18+
}
19+
20+
/// <summary>
21+
/// Visits IOpenApiReferenceable instances that are references and not in components.
22+
/// </summary>
23+
/// <param name="referenceable"> An IOpenApiReferenceable object.</param>
24+
public override void Visit(IOpenApiReferenceable referenceable)
25+
{
26+
switch (referenceable)
27+
{
28+
case OpenApiSchema schema:
29+
EnsureComponentsExists();
30+
EnsureSchemasExists();
31+
if (!Components.Schemas.ContainsKey(schema.Reference.Id))
32+
{
33+
Components.Schemas.Add(schema.Reference.Id, schema);
34+
}
35+
break;
36+
37+
case OpenApiParameter parameter:
38+
EnsureComponentsExists();
39+
EnsureParametersExists();
40+
if (!Components.Parameters.ContainsKey(parameter.Reference.Id))
41+
{
42+
Components.Parameters.Add(parameter.Reference.Id, parameter);
43+
}
44+
break;
45+
46+
case OpenApiResponse response:
47+
EnsureComponentsExists();
48+
EnsureResponsesExists();
49+
if (!Components.Responses.ContainsKey(response.Reference.Id))
50+
{
51+
Components.Responses.Add(response.Reference.Id, response);
52+
}
53+
break;
54+
55+
default:
56+
break;
57+
}
58+
base.Visit(referenceable);
59+
}
60+
61+
/// <summary>
62+
/// Visits <see cref="OpenApiSchema"/>
63+
/// </summary>
64+
/// <param name="schema">The OpenApiSchema to be visited.</param>
65+
public override void Visit(OpenApiSchema schema)
66+
{
67+
// This is needed to handle schemas used in Responses in components
68+
if (schema.Reference != null)
69+
{
70+
EnsureComponentsExists();
71+
EnsureSchemasExists();
72+
if (!Components.Schemas.ContainsKey(schema.Reference.Id))
73+
{
74+
Components.Schemas.Add(schema.Reference.Id, schema);
75+
}
76+
}
77+
base.Visit(schema);
78+
}
79+
80+
private void EnsureComponentsExists()
81+
{
82+
if (_target.Components == null)
83+
{
84+
_target.Components = new OpenApiComponents();
85+
}
86+
}
87+
88+
private void EnsureSchemasExists()
89+
{
90+
if (_target.Components.Schemas == null)
91+
{
92+
_target.Components.Schemas = new Dictionary<string, OpenApiSchema>();
93+
}
94+
}
95+
96+
private void EnsureParametersExists()
97+
{
98+
if (_target.Components.Parameters == null)
99+
{
100+
_target.Components.Parameters = new Dictionary<string, OpenApiParameter>();
101+
}
102+
}
103+
104+
private void EnsureResponsesExists()
105+
{
106+
if (_target.Components.Responses == null)
107+
{
108+
_target.Components.Responses = new Dictionary<string, OpenApiResponse>();
109+
}
110+
}
111+
}
112+
}

0 commit comments

Comments
 (0)