From c55849b8a2bf4f01e4428779ebabe491a917a451 Mon Sep 17 00:00:00 2001 From: Johannes Bader Date: Mon, 9 Jan 2017 15:42:20 -0800 Subject: [PATCH 1/2] composite external resolving revised --- .../AutoRest.CompositeSwagger/CompositeSwaggerModeler.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modeler/AutoRest.CompositeSwagger/CompositeSwaggerModeler.cs b/src/modeler/AutoRest.CompositeSwagger/CompositeSwaggerModeler.cs index 038a732f80..12af400f47 100644 --- a/src/modeler/AutoRest.CompositeSwagger/CompositeSwaggerModeler.cs +++ b/src/modeler/AutoRest.CompositeSwagger/CompositeSwaggerModeler.cs @@ -70,7 +70,9 @@ public override CodeModel Build() // merge child swaggers foreach (var childSwaggerPath in compositeSwaggerModel.Documents) { - var childSwagger = Settings.FileSystem.ReadFileAsText(childSwaggerPath).ParseYaml() as YamlMappingNode; + var childSwaggerRaw = Settings.FileSystem.ReadFileAsText(childSwaggerPath); + childSwaggerRaw = SwaggerParser.Normalize(childSwaggerPath, childSwaggerRaw); + var childSwagger = childSwaggerRaw.ParseYaml() as YamlMappingNode; if (childSwagger == null) { throw ErrorManager.CreateError("Failed parsing referenced Swagger file {0}.", childSwaggerPath); From cca42ba2e330319a6bc24388e339e5f36ddb5ca2 Mon Sep 17 00:00:00 2001 From: Johannes Bader Date: Mon, 9 Jan 2017 17:30:44 -0800 Subject: [PATCH 2/2] preprocessor (header resolving) --- .../AutoRest.Core/Parsing/YamlExtensions.cs | 2 +- src/core/AutoRest.Core/Settings.cs | 6 ++ src/core/AutoRest/Program.cs | 70 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/core/AutoRest.Core/Parsing/YamlExtensions.cs b/src/core/AutoRest.Core/Parsing/YamlExtensions.cs index 96da649a23..63f60713f1 100644 --- a/src/core/AutoRest.Core/Parsing/YamlExtensions.cs +++ b/src/core/AutoRest.Core/Parsing/YamlExtensions.cs @@ -74,7 +74,7 @@ public static string Serialize(this YamlNode node) { using (var writer = new StringWriter()) { - new YamlStream(new YamlDocument(node)).Save(writer); + new YamlStream(new YamlDocument(node)).Save(writer, false); return writer.ToString(); } } diff --git a/src/core/AutoRest.Core/Settings.cs b/src/core/AutoRest.Core/Settings.cs index 4ed9394f6e..0bee12ac63 100644 --- a/src/core/AutoRest.Core/Settings.cs +++ b/src/core/AutoRest.Core/Settings.cs @@ -309,6 +309,12 @@ public string Header [SettingsInfo("The input validation severity level that will prevent code generation")] public Category ValidationLevel { get; set; } + /// + /// If set, preprocesses a swagger file by expanding and resolving some advanced convenience syntax. + /// + [SettingsAlias("preprocessor")] + public bool Preprocessor { get; set; } + /// /// Factory method to generate CodeGenerationSettings from command line arguments. /// Matches dictionary keys to the settings properties. diff --git a/src/core/AutoRest/Program.cs b/src/core/AutoRest/Program.cs index 582010ba85..b3a09c6672 100644 --- a/src/core/AutoRest/Program.cs +++ b/src/core/AutoRest/Program.cs @@ -11,6 +11,10 @@ using AutoRest.Simplify; using static AutoRest.Core.Utilities.DependencyInjection; using System.IO; +using AutoRest.Core.Parsing; +using YamlDotNet.RepresentationModel; +using System.Collections.Generic; +using System.Text.RegularExpressions; namespace AutoRest { @@ -37,6 +41,13 @@ private static int Main(string[] args) settings.Verbose)); Logger.Instance.AddListener(new SignalingLogListener(Category.Error, _ => generationFailed = true)); + // internal preprocesor + if (settings.Preprocessor) + { + Console.Write(InternalPreprocessor(settings.FileSystem.ReadFileAsText(settings.Input))); + return 0; + } + // determine some reasonable default namespace if (settings.Namespace == null) { @@ -129,5 +140,64 @@ private static bool IsShowMarkdownHelpIncluded(string[] args) } return false; } + + private static string InternalPreprocessor(string preSwagger) + { + var yaml = preSwagger.ParseYaml() as YamlMappingNode; + + Func getHeaderNameFromRefPath = refPath => + { + var match = Regex.Match(refPath, @"\#\/headers/(?.*)"); + return match.Success + ? match.Groups["name"].Value + : null; + }; + + // resolve headers + var headersSection = yaml?.Get("headers") as YamlMappingNode; + if (headersSection != null) + { + var paths1 = (yaml.Get("paths") as YamlMappingNode)?.Select(x => x.Value) ?? new YamlNode[0]; + var paths2 = (yaml.Get("x-paths") as YamlMappingNode)?.Select(x => x.Value) ?? new YamlNode[0]; + var operations = paths1.Concat(paths2).OfType().SelectMany(x => x.Children).Select(x => x.Value).OfType(); + var responses = operations.Select(x => x.Get("responses")).OfType(); + var statusCodes = responses.SelectMany(x => x.Children).Select(x => x.Value).OfType(); + foreach (var statusCode in statusCodes.ToList()) + { + var headersNode = statusCode.Get("headers"); + var headersNodeMapping = headersNode as YamlMappingNode; + var headersNodeSequence = headersNode as YamlSequenceNode; + if (headersNodeMapping != null) + { + foreach (var header in headersNodeMapping.Children.ToList()) + { + var headerValue = header.Value as YamlMappingNode; + var refPath = (headerValue?.Get("$ref") as YamlScalarNode)?.Value; + if (refPath != null) + { + var refName = getHeaderNameFromRefPath(refPath); + headerValue = headerValue.MergeWith(headersSection.Get(refName) as YamlMappingNode); + headerValue.Remove("$ref"); + } + headersNodeMapping.Children[header.Key] = headerValue; + } + } + if (headersNodeSequence != null) + { + var headersNodeNew = new YamlMappingNode(); + foreach (var refPath in headersNodeSequence.Children.OfType().Select(x => x.Get("$ref")).OfType().Select(x => x.Value)) + { + var refName = getHeaderNameFromRefPath(refPath); + headersNodeNew.Add(refName, headersSection.Get(refName)); + } + statusCode.Set("headers", headersNodeNew); + } + } + + yaml.Remove("headers"); + } + + return yaml.Serialize(); + } } } \ No newline at end of file