From c4d05aa5a54cccbfd6ffa868753cf77b464cb769 Mon Sep 17 00:00:00 2001 From: Martin Strobel Date: Thu, 2 Feb 2017 14:18:52 -0800 Subject: [PATCH 1/4] Cache version strings after first generation. Also, rewrite CodeNamerGo method to be more readable and have fewer allocations. --- src/generator/AutoRest.Go/CodeNamerGo.cs | 21 +++++++------------ .../Templates/VersionTemplate.cshtml | 20 +++++++++++++++--- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/generator/AutoRest.Go/CodeNamerGo.cs b/src/generator/AutoRest.Go/CodeNamerGo.cs index 6392646879..35cce47488 100644 --- a/src/generator/AutoRest.Go/CodeNamerGo.cs +++ b/src/generator/AutoRest.Go/CodeNamerGo.cs @@ -11,6 +11,7 @@ using AutoRest.Core.Utilities.Collections; using AutoRest.Core.Model; using AutoRest.Go.Model; +using System.Text; namespace AutoRest.Go { @@ -412,20 +413,12 @@ public void ReserveNamespace(string ns) // camelCase or PascalCase. private string EnsureNameCase(string name) { - List words = new List(); - new List(name.ToWords()) - .ForEach(s => - { - if (CommonInitialisms.Contains(s)) - { - words.Add(s.ToUpper()); - } - else - { - words.Add(s); - } - }); - return String.Join(String.Empty, words.ToArray()); + var builder = new StringBuilder(); + foreach(var s in name.ToWords()) + { + builder.Append(CommonInitialisms.Contains(s) ? s.ToUpper() : s); + } + return builder.ToString(); } public static string[] SDKVersionFromPackageVersion(string v) diff --git a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml index 6ba8e4957b..87560e5b3b 100644 --- a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml +++ b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml @@ -24,18 +24,32 @@ const ( // Always begin a "tag" with a dash (as per http://semver.org) tag = "-beta" - semVerFormat = "%s.%s.%s%s" userAgentFormat = "Azure-SDK-For-Go/%s arm-%s/%s" ) +var userAgent string + @EmptyLine // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return fmt.Sprintf(userAgentFormat, Version(), "@(Model.Namespace)", "@(Model.ApiVersion)") + if userAgent == "" { + userAgent = fmt.Sprintf(userAgentFormat, Version(), "@(Model.Namespace)", "@(Model.ApiVersion)") + } + return userAgent } @EmptyLine +var version string + // Version returns the semantic version (see http://semver.org) of the client. func Version() string { - return fmt.Sprintf(semVerFormat, major, minor, patch, tag) + if version == "" { + versionBuilder := bytes.NewBufferString(fmt.Sprintf("%d.%d.%d", major, minor, patch)) + if tag != "" { + versionBuilder.WriteRune('-') + versionBuilder.WriteString(strings.TrimPrefix(tag, "-")) + } + version = string(versionBuilder.Bytes()) + } + return version } From eee0a2f40a59c5de067b54660e5fbf7c5e34a7b2 Mon Sep 17 00:00:00 2001 From: Martin Strobel Date: Thu, 2 Feb 2017 14:35:55 -0800 Subject: [PATCH 2/4] Responding to PR comments. --- src/generator/AutoRest.Go/CodeNamerGo.cs | 27 +++++++++++++------ .../Templates/VersionTemplate.cshtml | 11 ++++---- src/generator/AutoRest.Go/TransformerGo.cs | 4 +-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/generator/AutoRest.Go/CodeNamerGo.cs b/src/generator/AutoRest.Go/CodeNamerGo.cs index 35cce47488..e0e2015591 100644 --- a/src/generator/AutoRest.Go/CodeNamerGo.cs +++ b/src/generator/AutoRest.Go/CodeNamerGo.cs @@ -12,6 +12,7 @@ using AutoRest.Core.Model; using AutoRest.Go.Model; using System.Text; +using System.Text.RegularExpressions; namespace AutoRest.Go { @@ -30,12 +31,12 @@ public class CodeNamerGo : CodeNamer public virtual IEnumerable StandardImports => new string[] { "github.com/Azure/go-autorest/autorest/azure", "net/http" }; public virtual IEnumerable PageableImports => new string[] { "net/http", "github.com/Azure/go-autorest/autorest/to" }; - + public virtual IEnumerable ValidationImport => new string[] { "github.com/Azure/go-autorest/autorest/validation" }; // CommonInitialisms are those "words" within a name that Golint expects to be uppercase. // See https://github.com/golang/lint/blob/master/lint.go for detail. - private string[] CommonInitialisms => new string[] { + private static string[] CommonInitialisms => new string[] { "Acl", "Api", "Ascii", @@ -75,7 +76,7 @@ public class CodeNamerGo : CodeNamer "Xss", }; - public string[] UserDefinedNames => new string[] { + public static string[] UserDefinedNames => new string[] { "UserAgent", "Version", "APIVersion", @@ -87,6 +88,9 @@ public class CodeNamerGo : CodeNamer public IReadOnlyDictionary StatusCodeToGoString; + + private static readonly Regex semVerPattern = new Regex(@"^(?\d+)\.(?\d+)\.(?\d+)(?:-(?\S+))?$", RegexOptions.Compiled); + /// /// Initializes a new instance of CodeNamerGo. /// @@ -414,7 +418,7 @@ public void ReserveNamespace(string ns) private string EnsureNameCase(string name) { var builder = new StringBuilder(); - foreach(var s in name.ToWords()) + foreach (var s in name.ToWords()) { builder.Append(CommonInitialisms.Contains(s) ? s.ToUpper() : s); } @@ -427,12 +431,19 @@ public static string[] SDKVersionFromPackageVersion(string v) { throw new ArgumentNullException("package version"); } - string[] version = v.Split('.'); - if (version.Length != 3) + + var ver = semVerPattern.Match(v); + + if (ver.Success) { - throw new InvalidOperationException("version string should have major, minor and patch versions."); + var tagVal = ver.Groups["tag"].Success ? ver.Groups["tag"].Value : ""; + return new[] { ver.Groups["major"].Value, ver.Groups["minor"].Value, ver.Groups["patch"].Value, tagVal }; + } - return version; + throw new ArgumentException( + paramName: nameof(v), + message: "Version strings should be either of the format \"..\" or \"..-\". Where major, minor, and patch are decimal numbers and tag does not include whitespace."); + } public override string EscapeDefaultValue(string defaultValue, IModelType type) diff --git a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml index 87560e5b3b..cb1e5b52ea 100644 --- a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml +++ b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml @@ -21,13 +21,16 @@ const ( major = "@(Model.Version[0])" minor = "@(Model.Version[1])" patch = "@(Model.Version[2])" - // Always begin a "tag" with a dash (as per http://semver.org) - tag = "-beta" + tag = "@(Model.Version[3])" userAgentFormat = "Azure-SDK-For-Go/%s arm-%s/%s" ) -var userAgent string +// cached results of UserAgent and Version to prevent repeated operations. +var ( + userAgent string + version string +) @EmptyLine // UserAgent returns the UserAgent string to use when sending http.Requests. @@ -39,8 +42,6 @@ func UserAgent() string { } @EmptyLine -var version string - // Version returns the semantic version (see http://semver.org) of the client. func Version() string { if version == "" { diff --git a/src/generator/AutoRest.Go/TransformerGo.cs b/src/generator/AutoRest.Go/TransformerGo.cs index b89619898d..776833ec04 100644 --- a/src/generator/AutoRest.Go/TransformerGo.cs +++ b/src/generator/AutoRest.Go/TransformerGo.cs @@ -102,7 +102,7 @@ private void TransformEnumTypes(CodeModelGo cmg) cmg.EnumTypes.Cast().OrderBy(etg => etg.Name.Value) .ForEach(em => { - if (em.Values.Where(v => topLevelNames.Contains(v.Name) || CodeNamerGo.Instance.UserDefinedNames.Contains(v.Name)).Count() > 0) + if (em.Values.Where(v => topLevelNames.Contains(v.Name) || CodeNamerGo.UserDefinedNames.Contains(v.Name)).Count() > 0) { em.HasUniqueNames = false; } @@ -136,7 +136,7 @@ private void TransformModelTypes(CodeModelGo cmg) name = $"{name}Type"; } - if (CodeNamerGo.Instance.UserDefinedNames.Contains(name)) + if (CodeNamerGo.UserDefinedNames.Contains(name)) { name = $"{name}{cmg.Namespace.Capitalize()}"; } From 86ba14ad7be30bd6c5156a1d2f558d53af04a541 Mon Sep 17 00:00:00 2001 From: Martin Strobel Date: Thu, 2 Feb 2017 15:22:49 -0800 Subject: [PATCH 3/4] Adding missing package imports to template. --- src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml index cb1e5b52ea..4552319b0b 100644 --- a/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml +++ b/src/generator/AutoRest.Go/Templates/VersionTemplate.cshtml @@ -13,7 +13,9 @@ package @Model.Namespace @EmptyLine import ( + "bytes" "fmt" + "strings" ) @EmptyLine From 3c16fb53ec38f0c95ce027cb5f4567ea49a0bf73 Mon Sep 17 00:00:00 2001 From: Martin Strobel Date: Fri, 3 Feb 2017 12:13:49 -0800 Subject: [PATCH 4/4] Reversing change that made two fields static. --- src/generator/AutoRest.Go/CodeNamerGo.cs | 4 ++-- src/generator/AutoRest.Go/TransformerGo.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/generator/AutoRest.Go/CodeNamerGo.cs b/src/generator/AutoRest.Go/CodeNamerGo.cs index e0e2015591..d1dc6b9ccd 100644 --- a/src/generator/AutoRest.Go/CodeNamerGo.cs +++ b/src/generator/AutoRest.Go/CodeNamerGo.cs @@ -36,7 +36,7 @@ public class CodeNamerGo : CodeNamer // CommonInitialisms are those "words" within a name that Golint expects to be uppercase. // See https://github.com/golang/lint/blob/master/lint.go for detail. - private static string[] CommonInitialisms => new string[] { + private string[] CommonInitialisms => new string[] { "Acl", "Api", "Ascii", @@ -76,7 +76,7 @@ public class CodeNamerGo : CodeNamer "Xss", }; - public static string[] UserDefinedNames => new string[] { + public string[] UserDefinedNames => new string[] { "UserAgent", "Version", "APIVersion", diff --git a/src/generator/AutoRest.Go/TransformerGo.cs b/src/generator/AutoRest.Go/TransformerGo.cs index 776833ec04..b89619898d 100644 --- a/src/generator/AutoRest.Go/TransformerGo.cs +++ b/src/generator/AutoRest.Go/TransformerGo.cs @@ -102,7 +102,7 @@ private void TransformEnumTypes(CodeModelGo cmg) cmg.EnumTypes.Cast().OrderBy(etg => etg.Name.Value) .ForEach(em => { - if (em.Values.Where(v => topLevelNames.Contains(v.Name) || CodeNamerGo.UserDefinedNames.Contains(v.Name)).Count() > 0) + if (em.Values.Where(v => topLevelNames.Contains(v.Name) || CodeNamerGo.Instance.UserDefinedNames.Contains(v.Name)).Count() > 0) { em.HasUniqueNames = false; } @@ -136,7 +136,7 @@ private void TransformModelTypes(CodeModelGo cmg) name = $"{name}Type"; } - if (CodeNamerGo.UserDefinedNames.Contains(name)) + if (CodeNamerGo.Instance.UserDefinedNames.Contains(name)) { name = $"{name}{cmg.Namespace.Capitalize()}"; }