diff --git a/Microsoft.OpenApi.sln b/Microsoft.OpenApi.sln index c71f28228..e64ff3a24 100644 --- a/Microsoft.OpenApi.sln +++ b/Microsoft.OpenApi.sln @@ -26,6 +26,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6357D7FD-2 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.SmokeTests", "test\Microsoft.OpenApi.SmokeTests\Microsoft.OpenApi.SmokeTests.csproj", "{AD79B61D-88CF-497C-9ED5-41AE3867C5AC}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.OpenApi.Tool", "src\Microsoft.OpenApi.Tool\Microsoft.OpenApi.Tool.csproj", "{254841B5-7DAC-4D1D-A9C5-44FE5CE467BE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -56,6 +58,10 @@ Global {AD79B61D-88CF-497C-9ED5-41AE3867C5AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD79B61D-88CF-497C-9ED5-41AE3867C5AC}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD79B61D-88CF-497C-9ED5-41AE3867C5AC}.Release|Any CPU.Build.0 = Release|Any CPU + {254841B5-7DAC-4D1D-A9C5-44FE5CE467BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {254841B5-7DAC-4D1D-A9C5-44FE5CE467BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {254841B5-7DAC-4D1D-A9C5-44FE5CE467BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {254841B5-7DAC-4D1D-A9C5-44FE5CE467BE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -67,6 +73,7 @@ Global {AD83F991-DBF3-4251-8613-9CC54C826964} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} {1ED3C2C1-E1E7-4925-B4E6-2D969C3F5237} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} {AD79B61D-88CF-497C-9ED5-41AE3867C5AC} = {6357D7FD-2DE4-4900-ADB9-ABC37052040A} + {254841B5-7DAC-4D1D-A9C5-44FE5CE467BE} = {E546B92F-20A8-49C3-8323-4B25BB78F3E1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9F171EFC-0DB5-4B10-ABFA-AF48D52CC565} diff --git a/build.cmd b/build.cmd index 33f1be296..94f3ea8fc 100644 --- a/build.cmd +++ b/build.cmd @@ -1,5 +1,5 @@ @echo off -Echo Building Microsoft.OpenApi +Echo Building Microsoft.OpenApi SET PROJ=%~dp0src\Microsoft.OpenApi\Microsoft.OpenApi.csproj dotnet build %PROJ% /t:restore /p:Configuration=Release diff --git a/src/Microsoft.OpenApi.Readers/ParsingContext.cs b/src/Microsoft.OpenApi.Readers/ParsingContext.cs index 8cb9f5fd2..9c7277136 100644 --- a/src/Microsoft.OpenApi.Readers/ParsingContext.cs +++ b/src/Microsoft.OpenApi.Readers/ParsingContext.cs @@ -30,8 +30,15 @@ public class ParsingContext internal List Tags { get; private set; } = new List(); internal Uri BaseUrl { get; set; } + /// + /// Diagnostic object that returns metadata about the parsing process. + /// public OpenApiDiagnostic Diagnostic { get; } + /// + /// Create Parsing Context + /// + /// Provide instance for diagnotic object for collecting and accessing information about the parsing. public ParsingContext(OpenApiDiagnostic diagnostic) { Diagnostic = diagnostic; @@ -41,7 +48,6 @@ public ParsingContext(OpenApiDiagnostic diagnostic) /// Initiates the parsing process. Not thread safe and should only be called once on a parsing context /// /// Yaml document to parse. - /// Diagnostic object which will return diagnostic results of the operation. /// An OpenApiDocument populated based on the passed yamlDocument internal OpenApiDocument Parse(YamlDocument yamlDocument) { @@ -77,7 +83,6 @@ internal OpenApiDocument Parse(YamlDocument yamlDocument) /// /// /// OpenAPI version of the fragment - /// Diagnostic object which will return diagnostic results of the operation. /// An OpenApiDocument populated based on the passed yamlDocument internal T ParseFragment(YamlDocument yamlDocument, OpenApiSpecVersion version) where T : IOpenApiElement { diff --git a/src/Microsoft.OpenApi.Tool/Microsoft.OpenApi.Tool.csproj b/src/Microsoft.OpenApi.Tool/Microsoft.OpenApi.Tool.csproj new file mode 100644 index 000000000..f8f1eab1c --- /dev/null +++ b/src/Microsoft.OpenApi.Tool/Microsoft.OpenApi.Tool.csproj @@ -0,0 +1,25 @@ + + + + Exe + netcoreapp3.1 + true + openapi + ./../../artifacts + 0.5.0 + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs new file mode 100644 index 000000000..7a8e8ced2 --- /dev/null +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.OpenApi.Extensions; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Writers; + +namespace Microsoft.OpenApi.Tool +{ + static class OpenApiService + { + public static void ProcessOpenApiDocument( + FileInfo input, + FileInfo output, + OpenApiSpecVersion version, + OpenApiFormat format, + bool inline) + { + OpenApiDocument document; + using (Stream stream = input.OpenRead()) + { + + document = new OpenApiStreamReader(new OpenApiReaderSettings + { + ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences, + RuleSet = ValidationRuleSet.GetDefaultRuleSet() + } + ).Read(stream, out var context); + if (context.Errors.Count != 0) + { + var errorReport = new StringBuilder(); + + foreach (var error in context.Errors) + { + errorReport.AppendLine(error.ToString()); + } + + throw new ArgumentException(String.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())); + } + } + + using (var outputStream = output?.Create()) + { + TextWriter textWriter; + + if (outputStream!=null) + { + textWriter = new StreamWriter(outputStream); + } else + { + textWriter = Console.Out; + } + + var settings = new OpenApiWriterSettings() + { + ReferenceInline = inline == true ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences + }; + IOpenApiWriter writer; + switch (format) + { + case OpenApiFormat.Json: + writer = new OpenApiJsonWriter(textWriter, settings); + break; + case OpenApiFormat.Yaml: + writer = new OpenApiYamlWriter(textWriter, settings); + break; + default: + throw new ArgumentException("Unknown format"); + } + + document.Serialize(writer,version ); + + textWriter.Flush(); + } + } +} +} diff --git a/src/Microsoft.OpenApi.Tool/Program.cs b/src/Microsoft.OpenApi.Tool/Program.cs new file mode 100644 index 000000000..3d229c411 --- /dev/null +++ b/src/Microsoft.OpenApi.Tool/Program.cs @@ -0,0 +1,30 @@ +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.IO; +using System.Threading.Tasks; +using Microsoft.OpenApi; + +namespace Microsoft.OpenApi.Tool +{ + class Program + { + static async Task Main(string[] args) + { + var command = new RootCommand + { + new Option("--input") { Argument = new Argument() }, + new Option("--output") { Argument = new Argument() }, + new Option("--version") { Argument = new Argument() }, + new Option("--format") { Argument = new Argument() }, + new Option("--inline") { Argument = new Argument() } + }; + + command.Handler = CommandHandler.Create( + OpenApiService.ProcessOpenApiDocument); + + // Parse the incoming args and invoke the handler + return await command.InvokeAsync(args); + } + } +} diff --git a/src/Microsoft.OpenApi/Any/OpenApiString.cs b/src/Microsoft.OpenApi/Any/OpenApiString.cs index 00bfbe2cd..e1036cfca 100644 --- a/src/Microsoft.OpenApi/Any/OpenApiString.cs +++ b/src/Microsoft.OpenApi/Any/OpenApiString.cs @@ -14,6 +14,7 @@ public class OpenApiString : OpenApiPrimitive /// Initializes the class. /// /// + /// Used to indicate if a string is quoted. public OpenApiString(string value, bool isExplicit = false) : base(value) { diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs index f50f1c5f7..e14c98340 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs @@ -50,6 +50,7 @@ public static void SerializeAsYaml(this T element, Stream stream, OpenApiSpec /// The given stream. /// The Open API specification version. /// The output format (JSON or YAML). + /// Provide configuration settings for controlling writing output public static void Serialize( this T element, Stream stream, diff --git a/src/Microsoft.OpenApi/Services/LoopDetector.cs b/src/Microsoft.OpenApi/Services/LoopDetector.cs index 64001b22b..249cab51d 100644 --- a/src/Microsoft.OpenApi/Services/LoopDetector.cs +++ b/src/Microsoft.OpenApi/Services/LoopDetector.cs @@ -13,7 +13,6 @@ internal class LoopDetector /// /// Maintain history of traversals to avoid stack overflows from cycles /// - /// Any unique identifier for a stack. /// Identifier used for current context. /// If method returns false a loop was detected and the key is not added. public bool PushLoop(T key) @@ -39,7 +38,6 @@ public bool PushLoop(T key) /// /// Exit from the context in cycle detection /// - /// Identifier of loop public void PopLoop() { if (_loopStacks[typeof(T)].Count > 0) @@ -65,7 +63,6 @@ public void SaveLoop(T loop) /// /// Reset loop tracking stack /// - /// Identifier of loop to clear internal void ClearLoop() { _loopStacks[typeof(T)].Clear(); diff --git a/src/Microsoft.OpenApi/Services/OpenApiDifferenceOperation.cs b/src/Microsoft.OpenApi/Services/OpenApiDifferenceOperation.cs index 273763839..896c0a4d3 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiDifferenceOperation.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiDifferenceOperation.cs @@ -3,6 +3,8 @@ namespace Microsoft.OpenApi.Services { +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member + /// /// The open api difference operation. /// @@ -12,4 +14,6 @@ public enum OpenApiDifferenceOperation Remove, Update } +#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member + } diff --git a/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs b/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs index a0ea9de52..e4c3baa3c 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiJsonWriter.cs @@ -14,6 +14,7 @@ public class OpenApiJsonWriter : OpenApiWriterBase /// Initializes a new instance of the class. /// /// The text writer. + /// Settings for controlling how the OpenAPI document will be written out. public OpenApiJsonWriter(TextWriter textWriter, OpenApiWriterSettings settings = null) : base(textWriter, settings) { } diff --git a/test/Microsoft.OpenApi.SmokeTests/ApiGurus.cs b/test/Microsoft.OpenApi.SmokeTests/ApiGurus.cs index 79656c865..e424512ac 100644 --- a/test/Microsoft.OpenApi.SmokeTests/ApiGurus.cs +++ b/test/Microsoft.OpenApi.SmokeTests/ApiGurus.cs @@ -71,7 +71,7 @@ JToken GetProp(JToken obj, string prop) } // Disable as some APIs are currently invalid [Theory(DisplayName = "APIs.guru")] - [MemberData(nameof(GetSchemas))] + // [MemberData(nameof(GetSchemas))] public async Task EnsureThatICouldParse(string url) { var response = await _httpClient.GetAsync(url);