diff --git a/src/CodeGeneratorGo.cs b/src/CodeGeneratorGo.cs
index 3ad214a8c..b0fcdbf70 100644
--- a/src/CodeGeneratorGo.cs
+++ b/src/CodeGeneratorGo.cs
@@ -17,7 +17,6 @@ public class CodeGeneratorGo : CodeGenerator
private const string ModelsFileName = "models";
private const string ClientFileName = "client";
private const string VersionFileName = "version";
- private const string MarshallingFileName = "marshalling";
private const string ResponderFileName = "responder_policy";
private const string ResponseErrorFileName = "response_error";
private const string ValidationFileName = "validation";
@@ -33,7 +32,6 @@ public CodeGeneratorGo()
ModelsFileName,
ClientFileName,
VersionFileName,
- MarshallingFileName,
ResponderFileName,
ResponseErrorFileName,
ValidationFileName
@@ -101,12 +99,6 @@ public override async Task Generate(CodeModel cm)
{
await Write(template.Item1, FormatFileName(template.Item2));
}
-
- if (codeModel.RequiresMarshallers.Any())
- {
- var marshallingTemplate = new Marshalling { Model = codeModel };
- await Write(marshallingTemplate, FormatFileName(MarshallingFileName));
- }
}
///
diff --git a/src/CodeNamerGo.cs b/src/CodeNamerGo.cs
index 9df9a37fd..32ecb93fb 100644
--- a/src/CodeNamerGo.cs
+++ b/src/CodeNamerGo.cs
@@ -16,80 +16,28 @@ namespace AutoRest.Go
{
public class CodeNamerGo : CodeNamer
{
- public new static CodeNamerGo Instance
- {
- get
- {
- return (CodeNamerGo)CodeNamer.Instance;
- }
- }
+ public new static CodeNamerGo Instance => (CodeNamerGo)CodeNamer.Instance;
- public virtual IEnumerable PipelineImports
- {
- get
- {
- return new string[] { PrimaryTypeGo.GetImportLine(package: PipelineImportPath) };
- }
- }
+ public virtual IEnumerable PipelineImports => new [] { PrimaryTypeGo.GetImportLine(package: PipelineImportPath) };
public virtual IEnumerable StandardImports
{
get
{
- var imports = new List();
- imports.Add(PrimaryTypeGo.GetImportLine(package: "net/http"));
- imports.Add(PrimaryTypeGo.GetImportLine(package: "context"));
+ var imports = new List
+ {
+ PrimaryTypeGo.GetImportLine(package: "net/http"),
+ PrimaryTypeGo.GetImportLine(package: "context")
+ };
return imports;
}
}
- public virtual IEnumerable PageableImports => new string[]
+ public virtual IEnumerable PageableImports => new string[]
{
PrimaryTypeGo.GetImportLine(package: "net/http")
};
- // 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 HashSet CommonInitialisms => new HashSet(StringComparer.OrdinalIgnoreCase) {
- "Acl",
- "Api",
- "Ascii",
- "Cpu",
- "Css",
- "Dns",
- "Eof",
- "Guid",
- "Html",
- "Http",
- "Https",
- "Id",
- "Ip",
- "Json",
- "Lhs",
- "Qps",
- "Ram",
- "Rhs",
- "Rpc",
- "Sla",
- "Smtp",
- "Sql",
- "Ssh",
- "Tcp",
- "Tls",
- "Ttl",
- "Udp",
- "Ui",
- "Uid",
- "Uuid",
- "Uri",
- "Url",
- "Utf8",
- "Vm",
- "Xml",
- "Xsrf",
- "Xss",
- };
-
public string[] UserDefinedNames => new string[] {
"UserAgent",
"Version",
@@ -183,8 +131,8 @@ public CodeNamerGo()
"case", "defer", "go", "map", "struct",
"chan", "else", "goto", "package", "switch",
"const", "fallthrough", "if", "range", "type",
- "continue", "for", "import", "return", "var",
-
+ "continue", "for", "import", "return", "var",
+
// Reserved predeclared identifiers -- list retrieved from http://golang.org/ref/spec#Predeclared_identifiers
"bool", "byte",
"complex64", "complex128",
@@ -245,7 +193,7 @@ public CodeNamerGo()
"unsafe",
// Other reserved names and packages (defined by the base libraries this code uses)
- "autorest", "client", "date", "err", "req", "resp", "result", "sender", "to", "validation"
+ "autorest", "client", "date", "err", "req", "resp", "result", "sender", "to", "validation", "e", "d", "start"
});
}
@@ -273,7 +221,6 @@ public static string AttachTypeName(string name, string packageName, bool nameIn
/// Refactor -> Namer ... Even better if this already exists in the core :D
///
///
- ///
/// The formatted string
public override string PascalCase(string name)
{
@@ -283,59 +230,39 @@ public override string PascalCase(string name)
}
return
- name.Split(new Char[]{'.', '_', '@', '-', ' ', '$'})
+ name.Split('.', '_', '@', '-', ' ', '$')
.Where(s => !string.IsNullOrEmpty(s))
.Select(s => char.ToUpperInvariant(s[0]) + s.Substring(1, s.Length - 1))
.DefaultIfEmpty("")
.Aggregate(string.Concat);
}
- public override string GetEnumMemberName(string name)
- {
- return EnsureNameCase(base.GetEnumMemberName(name));
- }
+ public override string GetEnumMemberName(string name) => EnsureNameCase(base.GetEnumMemberName(name));
- public override string GetFieldName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(RemoveInvalidCharacters(PascalCase(GetEscapedReservedName(name, "Field"))));
- }
+ public override string GetFieldName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(RemoveInvalidCharacters(PascalCase(GetEscapedReservedName(name, "Field"))));
- public override string GetInterfaceName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(RemoveInvalidCharacters(PascalCase(name)));
- }
+ public override string GetInterfaceName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(RemoveInvalidCharacters(PascalCase(name)));
///
/// Formats a string for naming a method using Pascal case by default.
///
///
/// The formatted string.
- public override string GetMethodName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Method"));
- }
+ public override string GetMethodName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Method"));
- public override string GetMethodGroupName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
-
- return EnsureNameCase(RemoveInvalidCharacters(PascalCase(name)));
- }
+ public override string GetMethodGroupName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(RemoveInvalidCharacters(PascalCase(name)));
///
/// Formats a string for naming method parameters using Camel case by default.
@@ -348,7 +275,7 @@ public override string GetParameterName(string name)
{
return name;
}
- if (Extensions.StartsWithAcronym(name))
+ if (name.StartsWithAcronym())
{
return EnsureNameCase(GetEscapedReservedName((RemoveInvalidCharacters(name).ToLower()), "Parameter"));
}
@@ -360,42 +287,30 @@ public override string GetParameterName(string name)
///
///
/// The formatted string.
- public override string GetPropertyName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Property"));
- }
+ public override string GetPropertyName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Property"));
///
/// Formats a string for naming a Type or Object using Pascal case by default.
///
///
/// The formatted string.
- public override string GetTypeName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Type"));
- }
+ public override string GetTypeName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(GetEscapedReservedName(RemoveInvalidCharacters(PascalCase(name)), "Type"));
///
/// Formats a string for naming a local variable using Camel case by default.
///
///
/// The formatted string.
- public override string GetVariableName(string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- return name;
- }
- return EnsureNameCase(GetEscapedReservedName(CamelCase(RemoveInvalidCharacters(name)), "Var"));
- }
+ public override string GetVariableName(string name) =>
+ string.IsNullOrWhiteSpace(name) ?
+ name :
+ EnsureNameCase(GetEscapedReservedName(CamelCase(RemoveInvalidCharacters(name)), "Var"));
///
/// Converts names the conflict with Go reserved terms by appending the passed appendValue.
@@ -407,12 +322,12 @@ protected override string GetEscapedReservedName(string name, string appendValue
{
if (name == null)
{
- throw new ArgumentNullException("name");
+ throw new ArgumentNullException(nameof(name));
}
if (appendValue == null)
{
- throw new ArgumentNullException("appendValue");
+ throw new ArgumentNullException(nameof(appendValue));
}
// Use case-sensitive comparisons to reduce generated names
@@ -465,38 +380,45 @@ public override string EscapeDefaultValue(string defaultValue, IModelType type)
{
if (type == null)
{
- throw new ArgumentNullException("type");
+ throw new ArgumentNullException(nameof(type));
}
- PrimaryType primaryType = type as PrimaryType;
- if (defaultValue != null)
+ var primaryType = type as PrimaryType;
+
+ if (defaultValue == null)
{
- if (type is CompositeType)
- {
- return type.Name + "{}";
- }
- else if (primaryType != null)
- {
- if (primaryType.KnownPrimaryType == KnownPrimaryType.String
- || primaryType.KnownPrimaryType == KnownPrimaryType.Uuid
- || primaryType.KnownPrimaryType == KnownPrimaryType.TimeSpan
- || primaryType.IsDateTimeType())
- {
- return CodeNamer.Instance.QuoteValue(defaultValue);
- }
- else if (primaryType.KnownPrimaryType == KnownPrimaryType.Boolean)
- {
- return defaultValue.ToLowerInvariant();
- }
- else if (primaryType.KnownPrimaryType == KnownPrimaryType.ByteArray)
- {
- return "[]byte(\"" + defaultValue + "\")";
- }
- else
- {
- //TODO: handle imports for package types.
- }
- }
+ return null;
+ }
+
+ if (type is CompositeType)
+ {
+ return type.Name + "{}";
+ }
+
+ if (primaryType == null)
+ {
+ return defaultValue;
}
+
+ if (primaryType.KnownPrimaryType == KnownPrimaryType.String
+ || primaryType.KnownPrimaryType == KnownPrimaryType.Uuid
+ || primaryType.KnownPrimaryType == KnownPrimaryType.TimeSpan
+ || primaryType.IsDateTimeType())
+ {
+ return CodeNamer.Instance.QuoteValue(defaultValue);
+ }
+ else if (primaryType.KnownPrimaryType == KnownPrimaryType.Boolean)
+ {
+ return defaultValue.ToLowerInvariant();
+ }
+ else if (primaryType.KnownPrimaryType == KnownPrimaryType.ByteArray)
+ {
+ return "[]byte(\"" + defaultValue + "\")";
+ }
+ else
+ {
+ //TODO: handle imports for package types.
+ }
+
return defaultValue;
}
@@ -538,5 +460,47 @@ public string PipelineImportPath
/// Gets the type name for the etag type.
///
public string ETagTypeName => "ETag";
+
+ // 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 HashSet CommonInitialisms => new HashSet(StringComparer.OrdinalIgnoreCase) {
+ "Acl",
+ "Api",
+ "Ascii",
+ "Cpu",
+ "Css",
+ "Dns",
+ "Eof",
+ "Guid",
+ "Html",
+ "Http",
+ "Https",
+ "Id",
+ "Ip",
+ "Json",
+ "Lhs",
+ "Qps",
+ "Ram",
+ "Rhs",
+ "Rpc",
+ "Sla",
+ "Smtp",
+ "Sql",
+ "Ssh",
+ "Tcp",
+ "Tls",
+ "Ttl",
+ "Udp",
+ "Ui",
+ "Uid",
+ "Uuid",
+ "Uri",
+ "Url",
+ "Utf8",
+ "Vm",
+ "Xml",
+ "Xsrf",
+ "Xss",
+ };
}
}
diff --git a/src/Extensions.cs b/src/Extensions.cs
index cef03c17d..7ae5d1315 100644
--- a/src/Extensions.cs
+++ b/src/Extensions.cs
@@ -43,7 +43,7 @@ public static CodeModelGo Cast(this CodeModel cm)
}
///
- /// This method changes string to sentence where is make the first word
+ /// This method changes string to sentence where is make the first word
/// of sentence to lowercase (unless it is an acronym). The sentence is coming directly from swagger.
///
///
@@ -54,15 +54,13 @@ public static string ToSentence(this string value)
{
return string.Empty;
}
- else
+
+ value = value.Trim();
+ if (value.StartsWithAcronym())
{
- value = value.Trim();
- if (value.StartsWithAcronym())
- {
- return value;
- }
- return value.First().ToString().ToLowerInvariant() + (value.Length > 1 ? value.Substring(1) : "");
+ return value;
}
+ return value.First().ToString().ToLowerInvariant() + (value.Length > 1 ? value.Substring(1) : "");
}
///
@@ -74,7 +72,7 @@ public static string ToSentence(this string value)
public static bool StartsWithAcronym(this string value)
{
string firstWord = value.Trim().Split(' ', '-', '_').First();
- return firstWord.Length > 1 && firstWord.All(c => char.IsUpper(c));
+ return firstWord.Length > 1 && firstWord.All(char.IsUpper);
}
///
@@ -126,7 +124,7 @@ public static string ToShortName(this string longName)
}
///
- /// This method checks if MethodGroupName is plural of package name.
+ /// This method checks if MethodGroupName is plural of package name.
/// It returns false for packages not listed in dictionary 'plural'.
/// Example, group EventHubs in package EventHub.
/// Refactor -> Namer, but also could be used by the CodeModelTransformer
@@ -296,24 +294,43 @@ public static bool CanBeNull(this IModelType type)
///
public static void AddImports(this IModelType type, HashSet imports)
{
- if (type is DictionaryTypeGo)
+ switch (type)
{
- (type as DictionaryTypeGo).AddImports(imports);
- }
- else if (type is PrimaryTypeGo)
- {
- (type as PrimaryTypeGo).AddImports(imports);
- }
- else if (type is SequenceTypeGo)
- {
- (type as SequenceTypeGo).AddImports(imports);
+ case DictionaryTypeGo dictionaryType:
+ dictionaryType.AddImports(imports);
+ break;
+ case PrimaryTypeGo primaryType:
+ primaryType.AddImports(imports);
+ break;
+ default:
+ (type as SequenceTypeGo)?.AddImports(imports);
+ break;
}
}
public static bool ShouldBeSyntheticType(this IModelType type)
- {
- return (type is PrimaryType || type is SequenceType || type is DictionaryType || type is EnumType ||
- (type is CompositeTypeGo && (type as CompositeTypeGo).IsPolymorphicResponse()));
+ {
+ return (type is PrimaryType || type is SequenceType || type is DictionaryType || type is EnumType ||
+ (type is CompositeTypeGo && ((CompositeTypeGo) type).IsPolymorphicResponse()));
+ }
+
+ ///
+ /// Gets if the type has an interface.
+ ///
+ public static bool HasInterface(this IModelType type)
+ {
+ return (type is CompositeTypeGo compositeType) &&
+ (compositeType.IsRootType || compositeType.BaseIsPolymorphic && !compositeType.IsLeafType);
+ }
+
+ ///
+ /// Gets the interface name for the type.
+ ///
+ ///
+ ///
+ public static string GetInterfaceName(this IModelType type)
+ {
+ return $"Basic{type.Name}";
}
///
diff --git a/src/Model/CodeModelGo.cs b/src/Model/CodeModelGo.cs
index 1723f6403..985e24e94 100644
--- a/src/Model/CodeModelGo.cs
+++ b/src/Model/CodeModelGo.cs
@@ -20,13 +20,7 @@ public class CodeModelGo : CodeModel
public string Version { get; }
- public string UserAgent
- {
- get
- {
- return $"Azure-SDK-For-Go/{Version} arm-{Namespace}/{ApiVersion}";
- }
- }
+ public string UserAgent => $"Azure-SDK-For-Go/{Version} {Namespace}/{ApiVersion}";
public CodeModelGo()
{
@@ -37,33 +31,19 @@ public CodeModelGo()
public override string Namespace
{
- get
- {
- if (string.IsNullOrEmpty(base.Namespace))
- {
- return base.Namespace;
- }
-
- return base.Namespace.ToLowerInvariant();
- }
- set
- {
- base.Namespace = value;
- }
+ get => string.IsNullOrEmpty(base.Namespace) ? base.Namespace : base.Namespace.ToLowerInvariant();
+ set => base.Namespace = value;
}
public string ServiceName => CodeNamer.Instance.PascalCase(Namespace ?? string.Empty);
- public string GetDocumentation()
- {
- return $"Package {Namespace} implements the Azure ARM {ServiceName} service API version {ApiVersion}.\n\n{(Documentation ?? string.Empty).UnwrapAnchorTags()}";
- }
+ public string GetDocumentation() => $"Package {Namespace} implements the Azure ARM {ServiceName} service API version {ApiVersion}.\n\n{(Documentation ?? string.Empty).UnwrapAnchorTags()}";
public string BaseClient => CodeNamerGo.Instance.ExportClientTypes ? "ManagementClient" : "managementClient";
public bool IsCustomBaseUri => Extensions.ContainsKey(SwaggerExtensions.ParameterizedHostExtension);
- public string APIType => (string)Settings.Instance.Host?.GetValue("openapi-type").Result;
+ public string APIType => Settings.Instance.Host?.GetValue("openapi-type").Result;
public IEnumerable ClientImports
{
@@ -71,7 +51,7 @@ public IEnumerable ClientImports
{
var imports = new HashSet();
imports.UnionWith(CodeNamerGo.Instance.PipelineImports);
- var clientMg = MethodGroups.Where(mg => string.IsNullOrEmpty(mg.Name)).FirstOrDefault();
+ var clientMg = MethodGroups.FirstOrDefault(mg => string.IsNullOrEmpty(mg.Name));
if (clientMg != null)
{
imports.UnionWith(clientMg.Imports);
@@ -96,10 +76,12 @@ public IEnumerable ModelImports
var addStrConvImport = false;
var addBase64Import = false;
// Create an ordered union of the imports each model requires
- var imports = new HashSet();
- imports.Add(PrimaryTypeGo.GetImportLine(package: "net/http"));
- imports.Add(PrimaryTypeGo.GetImportLine(package: "reflect"));
- imports.Add(PrimaryTypeGo.GetImportLine(package: "strings"));
+ var imports = new HashSet
+ {
+ PrimaryTypeGo.GetImportLine(package: "net/http"),
+ PrimaryTypeGo.GetImportLine(package: "reflect"),
+ PrimaryTypeGo.GetImportLine(package: "strings")
+ };
ModelTypes.Cast()
.ForEach(mt =>
@@ -159,7 +141,7 @@ public string GlobalParameters
{
declarations.Add(
string.Format(
- (p.IsRequired || p.ModelType.CanBeNull() ? "{0} {1}" : "{0} *{1}"),
+ ((PropertyGo)p).IsPointer ? "{0} *{1}" : "{0} {1}",
p.Name.Value.ToSentence(), p.ModelType.Name));
}
}
@@ -194,7 +176,7 @@ public string GlobalDefaultParameters
{
declarations.Add(
string.Format(
- (p.IsRequired || p.ModelType.CanBeNull() ? "{0} {1}" : "{0} *{1}"),
+ (((PropertyGo)p).IsPointer ? "{0} *{1}" : "{0} {1}"),
p.Name.Value.ToSentence(), p.ModelType.Name.Value.ToSentence()));
}
}
@@ -269,14 +251,9 @@ public string HelperAllGlobalParameters
}
}
- public IEnumerable ClientMethods
- {
- get
- {
+ public IEnumerable ClientMethods =>
// client methods are the ones with no method group
- return Methods.Cast().Where(m => string.IsNullOrEmpty(m.MethodGroup.Name));
- }
- }
+ Methods.Cast().Where(m => string.IsNullOrEmpty(m.MethodGroup.Name));
/// FormatVersion normalizes a version string into a SemVer if it resembles one. Otherwise,
/// it returns the original string unmodified. If version is empty or only comprised of
@@ -313,36 +290,18 @@ public static string FormatVersion(string version)
///
/// Returns true if any model types contain a metadata property.
///
- public bool UsesMetadataType
- {
- get
- {
- return ModelTypes.Where(m => m.Properties.Cast().Where(p => p.IsMetadata).Any()).Any();
- }
- }
+ public bool UsesMetadataType => ModelTypes.Any(m => m.Properties.Cast().Any(p => p.IsMetadata));
///
/// Returns true if any model types contain an Etag property.
///
- public bool UsesETags
- {
- get
- {
- return ModelTypes.Where(m => m.Properties.Where(p => p.ModelType.IsETagType()).Any()).Any();
- }
- }
+ public bool UsesETags => ModelTypes.Any(m => m.Properties.Any(p => p.ModelType.IsETagType()));
///
- /// Returns a collection of composite types that require custom marshalling and/or
- /// unmarshalling. Can be empty if there are no types requriring marshallers.
+ /// Returns a collection of composite types that require datetime handleing in a custom marshaller and/or
+ /// unmarshaller. Can be empty if there are no types requriring marshallers.
///
- public IEnumerable RequiresMarshallers
- {
- get
- {
- return ModelTypes.Cast().Where(m => m.Properties.Where(p => p.ModelType.IsDateTimeType()).Any());
- }
- }
+ public IEnumerable RequiresDateTimeCustomHandling=> ModelTypes.Cast().Where(m => m.IsDateTimeCustomHandlingRequired);
///
/// Returns the encoding type used for serialization (e.g. xml or json).
diff --git a/src/Model/CompositeTypeGo.cs b/src/Model/CompositeTypeGo.cs
index daed5f90c..85ebe725d 100644
--- a/src/Model/CompositeTypeGo.cs
+++ b/src/Model/CompositeTypeGo.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using AutoRest.Core.Utilities.Collections;
using static AutoRest.Core.Utilities.DependencyInjection;
namespace AutoRest.Go.Model
@@ -16,57 +17,54 @@ namespace AutoRest.Go.Model
///
public class CompositeTypeGo : CompositeType
{
- private bool _wrapper;
+ public EnumType DiscriminatorEnum;
+
+ private CompositeTypeGo _rootType;
- // True if the type is returned by a method
+ ///
+ /// True if the type is returned by a method
+ ///
public bool IsResponseType;
- // Name of the field containing the URL used to retrieve the next result set
- // (null or empty if the model is not paged).
+ ///
+ /// Name of the field containing the URL used to retrieve the next result set (null or empty if the model is not paged).
+ ///
public string NextLink;
public bool PreparerNeeded = false;
+ public string DiscriminatorEnumValue => DiscriminatorEnum?.Values.FirstOrDefault(v => v.SerializedName.Equals(SerializedName))?.Name;
+
public IEnumerable DerivedTypes => CodeModel.ModelTypes.Where(t => t.DerivesFrom(this));
public IEnumerable SiblingTypes
{
get
{
- var st = (BaseModelType as CompositeTypeGo).DerivedTypes;
- if (BaseModelType.BaseModelType != null && BaseModelType.BaseModelType.IsPolymorphic)
+ var siblingTypes = RootType.DerivedTypes;
+
+ if (RootType.IsPolymorphic)
{
- st = st.Union((BaseModelType as CompositeTypeGo).SiblingTypes);
+ siblingTypes = siblingTypes.ConcatSingleItem(RootType);
}
- return st;
- }
- }
- public bool HasPolymorphicFields
- {
- get
- {
- return AllProperties.Any(p =>
- // polymorphic composite
- (p.ModelType is CompositeType && (p.ModelType as CompositeTypeGo).IsPolymorphic) ||
- // polymorphic array
- (p.ModelType is SequenceType && (p.ModelType as SequenceTypeGo).ElementType is CompositeType &&
- ((p.ModelType as SequenceTypeGo).ElementType as CompositeType).IsPolymorphic));
+ return siblingTypes;
}
}
- public EnumType DiscriminatorEnum;
-
- public string DiscriminatorEnumValue => DiscriminatorEnum.Values.FirstOrDefault(c => c.SerializedName.Equals(SerializedName)).Name;
+ public bool HasPolymorphicFields =>
+ AllProperties.Any(p =>
+ // polymorphic composite
+ p.ModelType.HasInterface() ||
+ // polymorphic array
+ (p.ModelType is SequenceType sequenceType && sequenceType.ElementType.HasInterface()));
public CompositeTypeGo()
{
-
}
public CompositeTypeGo(string name) : base(name)
{
-
}
public CompositeTypeGo(MethodGo responseToWrap)
@@ -95,14 +93,16 @@ public CompositeTypeGo(MethodGo responseToWrap)
if (!wrappedType.IsPrimaryType(KnownPrimaryType.Stream))
{
// add the wrapped type as a property named Value
- var p = new PropertyGo();
- p.Name = "Value";
- p.SerializedName = "value";
- p.ModelType = wrappedType;
+ var p = new PropertyGo
+ {
+ Name = "Value",
+ SerializedName = "value",
+ ModelType = wrappedType
+ };
Add(p);
}
-
- _wrapper = true;
+ AddPolymorphicPropertyIfNecessary();
+ IsWrapperType = true;
}
///
@@ -113,50 +113,68 @@ public CompositeTypeGo(MethodGo responseToWrap)
///
/// If PolymorphicDiscriminator is set, makes sure we have a PolymorphicDiscriminator property.
///
- private void AddPolymorphicPropertyIfNecessary()
+ internal void AddPolymorphicPropertyIfNecessary()
{
if (!string.IsNullOrEmpty(PolymorphicDiscriminator) && Properties.All(p => p.SerializedName != PolymorphicDiscriminator))
{
base.Add(New(new
{
- Name = CodeNamerGo.Instance.GetPropertyName(PolymorphicDiscriminator),
+ Name = PolymorphicDiscriminator,
SerializedName = PolymorphicDiscriminator,
- ModelType = DiscriminatorEnum,
+ ModelType = DiscriminatorEnum
}));
- }
- }
-
- public string PolymorphicProperty
- {
- get
- {
- if (!string.IsNullOrEmpty(PolymorphicDiscriminator))
- {
- return CodeNamerGo.Instance.GetPropertyName(PolymorphicDiscriminator);
- }
- if (BaseModelType != null)
- {
- return (BaseModelType as CompositeTypeGo).PolymorphicProperty;
- }
- return null;
}
}
- public IEnumerable AllProperties
+ ///
+ /// Gets if there are any flattened fields.
+ ///
+ public bool HasFlattenedFields => Properties.Any(p => p.ModelType is CompositeTypeGo && p.ShouldBeFlattened());
+
+ public string PolymorphicProperty => !string.IsNullOrEmpty(PolymorphicDiscriminator)
+ ? CodeNamerGo.Instance.GetPropertyName(PolymorphicDiscriminator)
+ : ((CompositeTypeGo) BaseModelType).PolymorphicProperty;
+
+ public IEnumerable AllProperties => BaseModelType != null ?
+ Properties.Cast().Concat(((CompositeTypeGo) BaseModelType).AllProperties) :
+ Properties.Cast();
+
+ ///
+ /// Gets the root type of the inheritance chain.
+ ///
+ public CompositeTypeGo RootType
{
get
{
- if (BaseModelType != null)
+ if (_rootType == null)
{
- return Properties.Cast().Concat((BaseModelType as CompositeTypeGo).AllProperties);
+
+ CompositeType rootModelType = this;
+ while (rootModelType.BaseModelType?.BaseIsPolymorphic == true)
+ {
+ rootModelType = rootModelType.BaseModelType;
+ }
+
+ _rootType = rootModelType as CompositeTypeGo;
}
- return Properties.Cast();
+
+ return _rootType;
}
}
+ ///
+ /// Gets if the type is a root type in an inheritance chain.
+ ///
+ public bool IsRootType => IsPolymorphic && RootType == this;
+
+ ///
+ /// Gets if the type is a leaf type in an inheritance chain.
+ ///
+ public bool IsLeafType => BaseIsPolymorphic && DerivedTypes.IsNullOrEmpty();
+
public override Property Add(Property item)
{
- var property = base.Add(item) as PropertyGo;
+ var property = base.Add(item);
AddPolymorphicPropertyIfNecessary();
return property;
}
@@ -169,15 +187,16 @@ public void AddImports(HashSet imports)
{
Properties.ForEach(p => p.ModelType.AddImports(imports));
- if (NeedsXmlNameField)
+ if (IsPolymorphic || HasFlattenedFields || NeedsXmlNameField)
{
- imports.Add(PrimaryTypeGo.GetImportLine(package: "encoding/xml"));
+ imports.Add($"\"encoding/{this.CodeModel.ToCodeModelGo().Encoding}\"");
}
- if (BaseIsPolymorphic && !IsPolymorphic)
+ if (IsDateTimeCustomHandlingRequired)
{
- imports.Add("\"encoding/json\"");
- imports.Add("\"errors\"");
+ imports.Add($"\"reflect\"");
+ imports.Add($"\"time\"");
+ imports.Add($"\"unsafe\"");
}
}
@@ -192,7 +211,7 @@ public bool IsPolymorphicResponse()
{
if (BaseIsPolymorphic && BaseModelType != null)
{
- return (BaseModelType as CompositeTypeGo).IsPolymorphicResponse();
+ return ((CompositeTypeGo) BaseModelType).IsPolymorphicResponse();
}
return IsPolymorphic && IsResponseType;
}
@@ -206,7 +225,7 @@ public string Fields(bool forMarshaller)
AddPolymorphicPropertyIfNecessary();
var indented = new IndentedStringBuilder(" ");
- // check if the XML name matches tyhe type name.
+ // check if the XML name matches the type name.
// if it doesn't then add an XMLName field.
if (NeedsXmlNameField)
{
@@ -228,18 +247,17 @@ public string Fields(bool forMarshaller)
{
indented.AppendFormat("// {0} - {1}\n", property.Name, property.Documentation);
}
- var enumType = property.ModelType as EnumTypeGo;
- if (enumType != null && enumType.IsNamed)
+
+ if (property.ModelType is EnumTypeGo enumType && enumType.IsNamed)
{
indented.AppendFormat("{0} {1} {2}\n",
property.Name,
enumType.Name,
property.Tag());
-
}
else if (property.ModelType is DictionaryType)
{
- var typeName = (property.ModelType as DictionaryTypeGo).Name;
+ var typeName = ((DictionaryTypeGo) property.ModelType).Name;
if (property.IsMetadata)
{
// use custom type instead of a map[string]string
@@ -263,9 +281,9 @@ public string Fields(bool forMarshaller)
// use custom type instead of *string
indented.Append($"{NextLink} Marker `{CodeModel.ToCodeModelGo().Encoding}:\"{NextLink}\"`");
}
- else if (property.ModelType is CompositeType && (property.ModelType as CompositeTypeGo).IsPolymorphic)
+ else if (property.ModelType is CompositeType && ((CompositeTypeGo) property.ModelType).IsPolymorphic)
{
- indented.AppendFormat("{0} {1} {2}\n", property.Name, property.ModelType.Name, property.Tag());
+ indented.AppendFormat("{0} {1} {2}\n", property.Name, property.ModelType.GetInterfaceName(), property.Tag());
}
else
{
@@ -275,7 +293,7 @@ public string Fields(bool forMarshaller)
property.Name = NextLink;
}
- var deref = property.ModelType.CanBeNull() || property.IsRequired ? string.Empty : "*";
+ var deref = property.IsPointer ? "*" : string.Empty;
var typeName = property.ModelType.Name.ToString();
if (forMarshaller && property.ModelType.IsDateTimeType())
{
@@ -292,21 +310,21 @@ public string Fields(bool forMarshaller)
return indented.ToString();
}
- public bool IsWrapperType => _wrapper;
+ public bool IsWrapperType { get; }
- public IModelType BaseType { get; private set; }
+ public IModelType BaseType { get; }
public IModelType GetElementType(IModelType type)
{
- if (type is SequenceTypeGo)
+ if (type is SequenceTypeGo sequenceType)
{
Name += "List";
- return GetElementType((type as SequenceType).ElementType);
+ return GetElementType(sequenceType.ElementType);
}
- else if (type is DictionaryTypeGo)
+ else if (type is DictionaryTypeGo dictionaryType)
{
Name += "Set";
- return GetElementType(((type as DictionaryTypeGo).ValueType));
+ return GetElementType(dictionaryType.ValueType);
}
else
{
@@ -370,7 +388,7 @@ public IEnumerable ResponseHeaders()
}
}
}
- respHeaders.Sort((lhs, rhs) => { return string.Compare(lhs.Name, rhs.Name, StringComparison.OrdinalIgnoreCase); });
+ respHeaders.Sort((lhs, rhs) => string.Compare(lhs.Name, rhs.Name, StringComparison.OrdinalIgnoreCase));
return respHeaders;
}
@@ -402,5 +420,7 @@ public bool ResponseIncludesMetadata
return false;
}
}
+
+ internal bool IsDateTimeCustomHandlingRequired => Properties.Any(p => p.ModelType.IsDateTimeType());
}
}
diff --git a/src/Model/EnumValueGo.cs b/src/Model/EnumValueGo.cs
index 0e2ed2da4..76a7a22ce 100644
--- a/src/Model/EnumValueGo.cs
+++ b/src/Model/EnumValueGo.cs
@@ -18,7 +18,7 @@ public static string FormatName(EnumTypeGo parent, EnumValueGo value)
// TODO: ideally the core would set the Parent field to that of the EnumTypeGo
// to which this belongs, for now this is how we work around that.
var parentName = parent.Name.ToString();
- return $"{parentName.Substring(0, parentName.Length - 4)}{value.Name}";
+ return $"{parentName.Substring(0, parentName.Length - 4)}{value.MemberName}";
}
}
}
diff --git a/src/Model/MethodGo.cs b/src/Model/MethodGo.cs
index d11639e8c..b0f639a0b 100644
--- a/src/Model/MethodGo.cs
+++ b/src/Model/MethodGo.cs
@@ -14,6 +14,7 @@
using System.Linq;
using System.Net;
using System.Text;
+using Newtonsoft.Json.Linq;
namespace AutoRest.Go.Model
{
@@ -21,13 +22,13 @@ public class MethodGo : Method
{
private const string DefaultResponseType = "http.Response";
- public new MethodGroupGo MethodGroup { get { return (MethodGroupGo)base.MethodGroup; } }
+ public new MethodGroupGo MethodGroup => (MethodGroupGo)base.MethodGroup;
public string PackageName { get; private set; }
public string APIVersion { get; private set; }
- private readonly string lroDescription = " This method may poll for completion. Polling can be canceled by passing the cancel channel argument. " +
+ private const string lroDescription = " This method may poll for completion. Polling can be canceled by passing the cancel channel argument. " +
"The channel will be used to cancel polling and any outstanding HTTP requests.";
public bool NextAlreadyDefined { get; private set; }
@@ -91,18 +92,18 @@ from p in Parameters
}
public string MethodSignature => $"{Name}({MethodParametersSignature(false)})";
-
+
public string MethodParametersSignatureComplete
{
get
- {
+ {
var signature = new StringBuilder("(");
signature.Append(MethodParametersSignature(false));
if (!IsLongRunningOperation())
{
if (MethodParametersSignature(false).Length > 0)
{
- signature.Append( ", ");
+ signature.Append(", ");
}
signature.Append("cancel <-chan struct{}");
}
@@ -151,7 +152,7 @@ public PropertyGo ListElement
get
{
var body = ReturnType.Body as CompositeTypeGo;
- return body.Properties.Where(p => p.ModelType is SequenceTypeGo).FirstOrDefault() as PropertyGo;
+ return body.Properties.FirstOrDefault(p => p.ModelType is SequenceTypeGo) as PropertyGo;
}
}
@@ -162,7 +163,7 @@ public PropertyGo ListElement
///
public string MethodParametersSignature(bool includeCtx)
{
- List declarations = new List();
+ var declarations = new List();
if (includeCtx)
{
@@ -178,9 +179,12 @@ public string MethodParametersSignature(bool includeCtx)
declarations.Add("body io.ReadSeeker");
continue;
}
+
declarations.Add(string.Format(localParam.IsPassedByValue()
? "{0} {1}"
- : "{0} *{1}", localParam.Name, localParam.ModelType.Name));
+ : "{0} *{1}", localParam.Name, localParam.ModelType.HasInterface()
+ ? localParam.ModelType.GetInterfaceName()
+ : localParam.ModelType.Name.ToString()));
}
return string.Join(", ", declarations);
@@ -198,24 +202,15 @@ public string MethodReturnType
{
return rv.Body.Name.ToString();
}
- else if (rv.Headers != null)
- {
- return rv.Headers.Name.ToString();
- }
- return DefaultResponseType;
+
+ return rv.Headers != null ? rv.Headers.Name.ToString() : DefaultResponseType;
}
}
///
/// Returns true if the method return type is the default response.
///
- public bool IsDefaultResponseType
- {
- get
- {
- return MethodReturnType == DefaultResponseType;
- }
- }
+ public bool IsDefaultResponseType => MethodReturnType == DefaultResponseType;
///
/// Returns the method return signature for this method (e.g. "foo, bar").
@@ -419,14 +414,13 @@ public IEnumerable SendDecorators
{
get
{
- var decorators = new List();
- decorators.Add("req");
- if (RegisterRP)
+ var decorators = new List
{
- decorators.Add("azure.DoRetryWithRegistration(client.Client)");
- } else {
- decorators.Add("autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)");
- }
+ "req",
+ RegisterRP
+ ? "azure.DoRetryWithRegistration(client.Client)"
+ : "autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...)"
+ };
if (IsLongRunningOperation())
{
decorators.Add("azure.DoPollForAsynchronous(client.PollingDelay)");
@@ -439,10 +433,12 @@ public IEnumerable RespondDecorators
{
get
{
- var decorators = new List();
- decorators.Add("resp");
- decorators.Add("client.ByInspecting()");
- decorators.Add(string.Format("azure.WithErrorUnlessStatusCode({0})", string.Join(",", ResponseCodes.ToArray())));
+ var decorators = new List
+ {
+ "resp",
+ "client.ByInspecting()",
+ string.Format("azure.WithErrorUnlessStatusCode({0})", string.Join(",", ResponseCodes.ToArray()))
+ };
var rvNeedsUnmarshalling = ReturnValueRequiresUnmarshalling();
if (rvNeedsUnmarshalling && !ReturnValue().Body.IsStreamType())
@@ -466,15 +462,9 @@ public IEnumerable RespondDecorators
}
}
- public string Response
- {
- get
- {
- return HasReturnValue()
- ? "result.Response = autorest.Response{Response: resp}"
- : "result.Response = resp";
- }
- }
+ public string Response => HasReturnValue()
+ ? "result.Response = autorest.Response{Response: resp}"
+ : "result.Response = resp";
///
/// Check if method has a return response.
@@ -510,8 +500,7 @@ public bool ReturnValueIsXmlWrapped()
return false;
}
- var ctg = ReturnValue().Body as CompositeTypeGo;
- if (ctg == null)
+ if (!(ReturnValue().Body is CompositeTypeGo ctg))
{
return false;
}
@@ -540,7 +529,7 @@ public bool BodyParamNeedsMarshalling()
}
///
- /// Checks if method has pageable extension (x-ms-pageable) enabled.
+ /// Checks if method has pageable extension (x-ms-pageable) enabled.
///
///
@@ -558,7 +547,7 @@ public bool NextMethodExists(IEnumerable methods)
string next = NextOperationName;
if (string.IsNullOrEmpty(next))
{
- return false;
+ return false;
}
return methods.Any(m => m.Name.Value.EqualsIgnoreCase(next));
}
@@ -579,16 +568,10 @@ public MethodGo NextMethod
}
}
- public string NextOperationName
- {
- get
- {
- return NextMethod?.Name.Value;
- }
- }
+ public string NextOperationName => NextMethod?.Name.Value;
///
- /// Check if method has long running extension (x-ms-long-running-operation) enabled.
+ /// Check if method has long running extension (x-ms-long-running-operation) enabled.
///
///
public bool IsLongRunningOperation()
@@ -626,19 +609,17 @@ public string NextLink
// Note:
// Methods can be paged, even if "nextLinkName" is null
// Paged method just means a method returns an array
- if (Extensions.ContainsKey(AzureExtensions.PageableExtension))
+ if (!Extensions.ContainsKey(AzureExtensions.PageableExtension))
{
- var pageableExtension = Extensions[AzureExtensions.PageableExtension] as Newtonsoft.Json.Linq.JContainer;
- if (pageableExtension != null)
- {
- var nextLink = (string)pageableExtension["nextLinkName"];
- if (!string.IsNullOrEmpty(nextLink))
- {
- return CodeNamerGo.Instance.GetPropertyName(nextLink);
- }
- }
+ return null;
}
- return null;
+ if (!(Extensions[AzureExtensions.PageableExtension] is JContainer pageableExtension))
+ {
+ return null;
+ }
+
+ var nextLink = (string)pageableExtension["nextLinkName"];
+ return !string.IsNullOrEmpty(nextLink) ? CodeNamerGo.Instance.GetPropertyName(nextLink) : null;
}
}
diff --git a/src/Model/ParameterGo.cs b/src/Model/ParameterGo.cs
index e03f3f174..5f3693956 100644
--- a/src/Model/ParameterGo.cs
+++ b/src/Model/ParameterGo.cs
@@ -123,7 +123,7 @@ public string DefaultValueString
}
///
- /// Get Name for parameter for Go map.
+ /// Get Name for parameter for Go map.
/// If parameter is client parameter, then return client.
///
///
@@ -254,12 +254,9 @@ public override IModelType ModelType
return base.ModelType;
}
// this is a header collection so emit it as a map[string]string
- return new DictionaryTypeGo() { ValueType = base.ModelType, CodeModel = base.ModelType.CodeModel, SupportsAdditionalProperties = false };
- }
- set
- {
- base.ModelType = value;
+ return new DictionaryTypeGo { ValueType = base.ModelType, CodeModel = base.ModelType.CodeModel, SupportsAdditionalProperties = false };
}
+ set => base.ModelType = value;
}
///
@@ -273,17 +270,18 @@ public string GetOptionalComparand()
throw new Exception($"GetOptionalComparand called on required paramater {Name}");
}
- if (ModelType is EnumTypeGo)
+ if (!(ModelType is EnumTypeGo et))
{
- var et = ModelType as EnumTypeGo;
- var typeName = et.Name.ToString();
- if (typeName.EndsWith("Type"))
- {
- typeName = typeName.Substring(0, typeName.Length - 4);
- }
- return $"{typeName}None";
+ return "nil";
}
- return "nil";
+
+ var typeName = et.Name.ToString();
+ if (typeName.EndsWith("Type"))
+ {
+ typeName = typeName.Substring(0, typeName.Length - 4);
+ }
+
+ return $"{typeName}None";
}
///
@@ -308,7 +306,7 @@ public static class ParameterGoExtensions
///
public static string Format(this ParameterGo parameter)
{
- return parameter.IsPassedByValue() ? "{0}" : "*{0}";
+ return parameter.IsPassedByValue() ? "{0}" : "*{0}";
}
///
@@ -346,7 +344,7 @@ public static string GetStringFormat(this ParameterGo parameter, string defaultF
// e.g. (*fooparam).Format(rfc339Format)
defaultFormat = $"({defaultFormat})";
}
-
+
if (parameter.ModelType.IsPrimaryType(KnownPrimaryType.DateTimeRfc1123))
{
return $"{defaultFormat}.In(gmt).Format(time.RFC1123)";
@@ -373,7 +371,7 @@ public static string BuildParameterMap(this IEnumerable parameters,
builder.Append(mapVariable);
builder.Append(" := map[string]interface{} {");
- if (parameters.Count() > 0)
+ if (parameters.Any())
{
builder.AppendLine();
var indented = new IndentedStringBuilder(" ");
diff --git a/src/Model/PropertyGo.cs b/src/Model/PropertyGo.cs
index 2ea8a0423..e760bc7ef 100644
--- a/src/Model/PropertyGo.cs
+++ b/src/Model/PropertyGo.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
-using AutoRest.Core.Utilities;
using AutoRest.Core.Model;
using AutoRest.Extensions;
using System;
@@ -13,10 +12,9 @@ public class PropertyGo : Property
{
public PropertyGo()
{
-
}
- public string Tag()
+ public string Tag(bool omitEmpty = true)
{
// don't emit a tag if this property is part of a parameter group (it's not necessary)
if (Extensions.ContainsKey(SwaggerExtensions.ParameterGroupExtension))
@@ -24,49 +22,72 @@ public string Tag()
return string.Empty;
}
- if (Parent.CodeModel.ShouldGenerateXmlSerialization)
+ if (!Parent.CodeModel.ShouldGenerateXmlSerialization)
{
- var sb = new StringBuilder("`xml:\"");
+ return string.Format("`json:\"{0}{1}\"`", SerializedName, omitEmpty ? ",omitempty" : "");
+ }
- bool hasParent = false;
- if (Parent is CompositeTypeGo && !((CompositeTypeGo)Parent).IsWrapperType)
- {
- sb.Append(XmlName);
- hasParent = true;
- }
+ var sb = new StringBuilder("`xml:\"");
- if (XmlIsWrapped)
- {
- if (hasParent)
- {
- sb.Append('>');
- }
+ bool hasParent = false;
+ if (Parent is CompositeTypeGo go && !go.IsWrapperType)
+ {
+ sb.Append(XmlName);
+ hasParent = true;
+ }
- var asSequence = ModelType as SequenceTypeGo;
- sb.Append(asSequence.ElementXmlName);
- }
- else if (XmlIsAttribute)
+ if (XmlIsWrapped)
+ {
+ if (hasParent)
{
- sb.Append(",attr");
+ sb.Append('>');
}
- sb.Append("\"`");
- return sb.ToString();
+ var asSequence = ModelType as SequenceTypeGo;
+ sb.Append(asSequence.ElementXmlName);
}
+ else if (XmlIsAttribute)
+ {
+ sb.Append(",attr");
+ }
+
+ sb.Append("\"`");
+ return sb.ToString();
- return string.Format("`json:\"{0},omitempty\"`", SerializedName);
}
+ ///
+ /// Gets if the property should be treated as a pointer
+ ///
+ public bool IsPointer => !(this.ModelType.HasInterface() || IsRequired || ModelType.CanBeNull() || ModelType is EnumTypeGo);
+
///
/// Returns true if this property represents custom metadata.
///
- public bool IsMetadata
+ public bool IsMetadata => string.Compare(Name, "Metadata", StringComparison.OrdinalIgnoreCase) == 0 && ModelType is DictionaryTypeGo;
+
+ ///
+ /// Determiens if this PropertyGo instance is equal to another.
+ ///
+ ///
+ ///
+ public override bool Equals(object value)
{
- get
+ if (value is PropertyGo goProperty)
{
- // unfortunately we have to use a heuristic
- return string.Compare(Name, "Metadata", StringComparison.OrdinalIgnoreCase) == 0 && ModelType is DictionaryTypeGo;
+ return goProperty.Name == Name;
}
+
+ return false;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// A 32-bit signed integer hash code.
+ public override int GetHashCode()
+ {
+ return Name.GetHashCode();
}
}
}
diff --git a/src/Model/SequenceTypeGo.cs b/src/Model/SequenceTypeGo.cs
index 1e408c39c..7923b63a9 100644
--- a/src/Model/SequenceTypeGo.cs
+++ b/src/Model/SequenceTypeGo.cs
@@ -8,9 +8,12 @@ namespace AutoRest.Go.Model
{
public class SequenceTypeGo : SequenceType
{
- public SequenceTypeGo() : base()
+ public SequenceTypeGo()
{
- Name.OnGet += v => $"[]{ElementType.Name}";
+ Name.OnGet += v =>
+ ElementType.HasInterface() ?
+ $"[]{ElementType.GetInterfaceName()}" :
+ $"[]{ElementType.Name}";
}
///
diff --git a/src/Templates/EnumTemplate.cshtml b/src/Templates/EnumTemplate.cshtml
index e0a9a44f8..84a34aa6d 100644
--- a/src/Templates/EnumTemplate.cshtml
+++ b/src/Templates/EnumTemplate.cshtml
@@ -1,33 +1,50 @@
-@using AutoRest.Go
+@using System.Collections.Generic
+@using AutoRest.Go
@using AutoRest.Go.Model
@using System.Linq
@inherits AutoRest.Core.Template
-@{
- var values = Model.Values.Cast().OrderBy(v => v.Name);
-}
@WrapComment("// ", Model.Documentation)
type @Model.Name string
+
@EmptyLine
-@if (values.Any())
+@if (Model.Values.Any())
{
-
-const (
- @foreach (var v in values)
- {
- var valName = EnumValueGo.FormatName(Model, v);
- var desc = v.Description;
- if (string.IsNullOrWhiteSpace(desc))
+ var possibleFuncName = $"Possible{Model.Name}Values";
+ var orderedValues = new List();
+
+ const (
+ @foreach (var v in Model.Values.OrderBy(v => v.Name))
{
- desc = string.Format("{0} ...", valName);
+ var comment = string.Empty;
+ var memName = CodeNamerGo.Instance.GetEnumMemberName(v.Name);
+ orderedValues.Add(memName);
+
+ if (string.IsNullOrWhiteSpace(v.Description))
+ {
+ comment = $"{CodeNamerGo.Instance.GetEnumMemberName(v.Name)} ...";
+
+
+ // @comment
+
+ }
+ else
+ {
+ comment = $"{CodeNamerGo.Instance.GetEnumMemberName(v.Name)} {v.Description}";
+
+ @WrapComment("// ", comment)
+
+ }
+
+ @(memName) @(Model.Name) = "@(v.SerializedName)"
+
+ }
+ )
+ // @possibleFuncName returns an array of possible values for the @Model.Name const type.
+ func @(possibleFuncName)() []@Model.Name {
+ return []@(Model.Name){@(string.Join(',', orderedValues))}
}
-
- @WrapComment("// ", desc)
- @(valName) @(Model.Name) = "@(v.SerializedName)"
- }
-)
-
}
diff --git a/src/Templates/Marshalling.cshtml b/src/Templates/Marshalling.cshtml
index 9c1ebe08a..83950dfd1 100644
--- a/src/Templates/Marshalling.cshtml
+++ b/src/Templates/Marshalling.cshtml
@@ -7,18 +7,6 @@
@using System.Linq
@inherits AutoRest.Core.Template
-package @Model.Namespace
-@EmptyLine
-@Header("// ")
-
-@EmptyLine
-
-import (
- "encoding/xml"
- "reflect"
- "time"
- "unsafe"
-)
const (
rfc3339Format = "2006-01-02T15:04:05.0000000Z07:00"
@@ -59,33 +47,13 @@ func (t *timeRFC3339) UnmarshalText(data []byte) (err error) {
return
}
-@foreach (var ct in Model.RequiresMarshallers)
+@foreach (var ct in Model.RequiresDateTimeCustomHandling)
{
var internalName = ct.Name.ToCamelCase();
- var rec = ct.Name.ToString().ToShortName();
- var local = $"{rec}2";
// internal type used for marshalling
type @internalName struct {
@ct.Fields(true)
}
-
-// MarshalXML implements the xml.Marshaler interface for @ct.Name.
-func (@rec @ct.Name) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- if reflect.TypeOf((*@ct.Name)(nil)).Elem().Size() != reflect.TypeOf((*@internalName)(nil)).Elem().Size() {
- panic("size mismatch between @ct.Name and @internalName")
- }
- @local := (*@internalName)(unsafe.Pointer(&@rec))
- return e.EncodeElement(*@local, start)
-}
-
-// UnmarshalXML implements the xml.Unmarshaler interface for @ct.Name.
-func (@rec *@ct.Name) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- if reflect.TypeOf((*@ct.Name)(nil)).Elem().Size() != reflect.TypeOf((*@internalName)(nil)).Elem().Size() {
- panic("size mismatch between @ct.Name and @internalName")
- }
- @local := (*@internalName)(unsafe.Pointer(@rec))
- return d.DecodeElement(@local, &start)
-}
}
diff --git a/src/Templates/MarshallingJson.cshtml b/src/Templates/MarshallingJson.cshtml
new file mode 100644
index 000000000..335deeaf0
--- /dev/null
+++ b/src/Templates/MarshallingJson.cshtml
@@ -0,0 +1,160 @@
+@using AutoRest.Core.Model
+@using AutoRest.Core.Utilities
+@using AutoRest.Go
+@using AutoRest.Go.Model
+@using AutoRest.Go.Templates
+@using System.Collections.Generic
+@using System.Linq
+@inherits AutoRest.Core.Template
+@EmptyLine
+
+@if (Model.HasInterface())
+{
+
+ func unmarshal@(Model.GetInterfaceName())(body []byte) (@(Model.GetInterfaceName()), error){
+ var m map[string]interface{}
+ err := json.Unmarshal(body, &m)
+ if err != nil {
+ return nil, err
+ }
+ @EmptyLine
+ switch m["@(Model.RootType.PolymorphicDiscriminator)"] {
+ @foreach (var dt in Model.DerivedTypes)
+ {
+
+ case string(@CodeNamerGo.Instance.GetEnumMemberName(((CompositeTypeGo) dt).DiscriminatorEnumValue)):
+ var @(dt.Name.FixedValue.ToShortName()) @(dt.Name)
+ err := json.Unmarshal(body, &@(dt.Name.FixedValue.ToShortName()))
+ return @(dt.Name.FixedValue.ToShortName()), err
+
+ }
+ default:
+ var @(Model.Name.FixedValue.ToShortName()) @(Model.Name)
+ err := json.Unmarshal(body, &@(Model.Name.FixedValue.ToShortName()))
+ return @(Model.Name.FixedValue.ToShortName()), err
+ }
+ }
+
+ func unmarshal@(Model.GetInterfaceName())Array(body []byte) ([]@(Model.GetInterfaceName()), error){
+ var rawMessages []*json.RawMessage
+ err := json.Unmarshal(body, &rawMessages)
+ if err != nil {
+ return nil, err
+ }
+ @EmptyLine
+ @(Model.Name.FixedValue.ToShortName())Array := make([]@(Model.GetInterfaceName()), len(rawMessages))
+ @EmptyLine
+ for index, rawMessage := range rawMessages {
+ @(Model.Name.FixedValue.ToShortName()), err := unmarshal@(Model.GetInterfaceName())(*rawMessage)
+ if err != nil {
+ return nil, err
+ }
+ @(Model.Name.FixedValue.ToShortName())Array[index] = @(Model.Name.FixedValue.ToShortName())
+ }
+ return @(Model.Name.FixedValue.ToShortName())Array, nil
+ }
+
+}
+
+@if (Model.BaseIsPolymorphic || Model.IsPolymorphic)
+{
+
+ @EmptyLine
+ // MarshalJSON is the custom marshaler for @(Model.Name).
+ func (@(Model.Name.FixedValue.ToShortName()) @(Model.Name))MarshalJSON() ([]byte, error){
+ @(Model.Name.FixedValue.ToShortName()).@(Model.PolymorphicProperty) = @(Model.DiscriminatorEnumValue)
+ type Alias @(Model.Name)
+ return json.Marshal(&struct {
+ Alias
+ }{
+ Alias: (Alias)(@(Model.Name.FixedValue.ToShortName())),
+ })
+ }
+
+}
+
+@if (Model.HasPolymorphicFields || Model.HasFlattenedFields)
+{
+
+ // UnmarshalJSON is the custom unmarshaler for @(Model.Name) struct.
+ func (@(Model.Name.FixedValue.ToShortName()) *@(Model.Name)) UnmarshalJSON(body []byte) error {
+ @if (Model.IsWrapperType)
+ {
+ if (Model.BaseType is SequenceTypeGo sequenceType)
+ {
+ @:@(sequenceType.ElementType.Name.FixedValue.ToShortName()), err := unmarshal@(sequenceType.ElementType.GetInterfaceName())Array(body)
+ }
+ else
+ {
+ @:@(Model.BaseType.Name.FixedValue.ToShortName()), err := unmarshal@(Model.BaseType.GetInterfaceName())(body)
+ }
+
+ if err != nil {
+ return err
+ }
+
+ if (Model.BaseType is SequenceType type)
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).Value = &@type.ElementType.Name.FixedValue.ToShortName()
+ }
+ else
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).Value = @(Model.BaseType.Name.FixedValue.ToShortName())
+ }
+}
+else
+{
+
+ var m map[string]*json.RawMessage
+ err := json.Unmarshal(body, &m)
+ if err != nil {
+ return err
+ }
+
+ var v *json.RawMessage
+ @foreach (var p in Model.AllProperties)
+ {
+
+ @EmptyLine
+ v = m["@(p.SerializedName)"]
+ if v != nil {
+ @if (p.ModelType.HasInterface())
+ {
+ @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(p.ModelType.GetInterfaceName())(*m["@(p.SerializedName)"])
+ }
+ else if (p.ModelType is SequenceTypeGo sequenceType && sequenceType.ElementType.HasInterface())
+ {
+ @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(sequenceType.ElementType.GetInterfaceName())Array(*m["@(p.SerializedName)"])
+ }
+ else if (p.ModelType is CompositeType && ((CompositeTypeGo)p.ModelType).IsPolymorphic)
+ {
+ @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(p.ModelType.Name)(*m["@(p.SerializedName)"])
+ }
+ else
+ {
+
+ var @(CodeNamerGo.Instance.GetVariableName(p.SerializedName)) @(p.ModelType.Name)
+ err = json.Unmarshal(*m["@(p.SerializedName)"], &@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)))
+
+}
+ if err != nil {
+ return err
+ }
+ @if (p.ModelType.HasInterface() || p.ModelType is EnumType)
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = @(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
+ }
+ else
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = &@(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
+ }
+ }
+
+ }
+
+ }
+ @EmptyLine
+ return nil
+ }
+
+ }
\ No newline at end of file
diff --git a/src/Templates/MarshallingXml.cshtml b/src/Templates/MarshallingXml.cshtml
new file mode 100644
index 000000000..7229c946e
--- /dev/null
+++ b/src/Templates/MarshallingXml.cshtml
@@ -0,0 +1,194 @@
+@using AutoRest.Core.Model
+@using AutoRest.Core.Utilities
+@using AutoRest.Go
+@using AutoRest.Go.Model
+@using AutoRest.Go.Templates
+@using System.Collections.Generic
+@using System.Linq
+@inherits AutoRest.Core.Template
+@EmptyLine
+
+@if (Model.HasInterface())
+{
+
+ func unmarshal@(Model.GetInterfaceName())(d *xml.Decoder, start xml.StartElement) (@(Model.GetInterfaceName()), error){
+ switch start.Name.Local {
+ @foreach (var dt in Model.DerivedTypes)
+ {
+
+ case string(@CodeNamerGo.Instance.GetEnumMemberName(((CompositeTypeGo)dt).DiscriminatorEnumValue)):
+ var @(dt.Name.FixedValue.ToShortName()) @(dt.Name)
+ err := d.DecodeElement(&@(dt.Name.FixedValue.ToShortName()), &start)
+ if err == nil {
+ @(dt.Name.FixedValue.ToShortName()).@(Model.DiscriminatorEnum.Name.Value) = @CodeNamerGo.Instance.GetEnumMemberName(((CompositeTypeGo)dt).DiscriminatorEnumValue)
+ }
+ return @(dt.Name.FixedValue.ToShortName()), err
+
+}
+ default:
+ var @(Model.Name.FixedValue.ToShortName()) @(Model.Name)
+ err := d.DecodeElement(&@(Model.Name.FixedValue.ToShortName()), &start)
+ if err == nil {
+ @(Model.Name.FixedValue.ToShortName()).@(Model.DiscriminatorEnum.Name.Value) = @CodeNamerGo.Instance.GetEnumMemberName(((CompositeTypeGo)Model).DiscriminatorEnumValue)
+ }
+ return @(Model.Name.FixedValue.ToShortName()), err
+ }
+
+ }
+
+ func unmarshal@(Model.GetInterfaceName())Array(d *xml.Decoder, start xml.StartElement) ([]@(Model.GetInterfaceName()), error){
+ @(Model.Name.FixedValue.ToShortName())Array := []@(Model.GetInterfaceName()){}
+
+ for t, err := d.Token(); err == nil; t, err = d.Token() {
+ ttStart, ok := t.(xml.StartElement)
+ if ok {
+ @(Model.Name.FixedValue.ToShortName()), err := unmarshal@(Model.GetInterfaceName())(d, ttStart)
+ if err == nil {
+ @(Model.Name.FixedValue.ToShortName())Array = append(@(Model.Name.FixedValue.ToShortName())Array, @(Model.Name.FixedValue.ToShortName()))
+ }
+ }
+
+ ttEnd, ok := t.(xml.EndElement)
+ if ok && start.End() == ttEnd {
+ break;
+ }
+ continue;
+ }
+ return @(Model.Name.FixedValue.ToShortName())Array, nil
+ }
+
+ }
+
+@if (Model.BaseIsPolymorphic || Model.IsPolymorphic)
+{
+
+ @EmptyLine
+ // MarshalXML is the custom marshaler for @(Model.Name).
+ func (@(Model.Name.FixedValue.ToShortName()) @(Model.Name))MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ @(Model.Name.FixedValue.ToShortName()).@(Model.PolymorphicProperty) = @(Model.DiscriminatorEnumValue)
+ type Alias @(Model.Name)
+ return e.EncodeElement(struct {
+ Alias
+ }{
+ Alias: (Alias)(@(Model.Name.FixedValue.ToShortName())),
+ }, start)
+ }
+
+}
+
+@if (Model.HasPolymorphicFields || Model.HasFlattenedFields)
+{
+ var attrProperties = Model.AllProperties.Where(p => p.XmlIsAttribute);
+ var nonAttrProperties = Model.AllProperties.Where(p => !p.XmlIsAttribute);
+
+
+ // UnmarshalXML is the custom unmarshaler for @(Model.Name) struct.
+ func (@(Model.Name.FixedValue.ToShortName()) *@(Model.Name)) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+
+ for _, a := range start.Attr {
+ switch a.Name.Local {
+ @foreach (var p in attrProperties)
+ {
+
+ case "@p.Name":
+ @if (p.IsPointer)
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).@p.Name = &a.Value
+ }
+ else
+ {
+ @:@(Model.Name.FixedValue.ToShortName()).@p.Name = a.Value
+ }
+
+}
+ }
+ }
+
+ for t, err := d.Token(); err == nil; t, err = d.Token() {
+ tt, ok := t.(xml.StartElement)
+ if !ok {
+ continue
+ }
+ switch tt.Name.Local {
+ @foreach (var p in nonAttrProperties)
+ {
+ @:case "@p.Name":
+
+ @if (p.ModelType.HasInterface())
+ {
+ @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(p.ModelType.GetInterfaceName())(d, tt)
+ @:if err != nil {
+ @: return err
+ @:}
+ @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = @(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
+ }
+ else if (p.ModelType is SequenceTypeGo sequenceType && sequenceType.ElementType.HasInterface())
+ {
+ @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(sequenceType.ElementType.GetInterfaceName())Array(d, tt)
+ @:if err != nil {
+ @: return err
+ @:}
+ @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = @(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
+ }
+ else
+ {
+ @:err := d.DecodeElement(&@(Model.Name.FixedValue.ToShortName()).@p.Name, &tt)
+ @:if err != nil {
+ @: return err
+ @:}
+ }
+
+
+ }
+ }
+ }
+ return nil
+ }
+
+ }
+
+@if (Model.ResponseIncludesMetadata)
+{
+ var shortName = Model.Name.ToString().ToShortName();
+
+
+ // NewMetadata returns user-defined key/value pairs.
+ func(@shortName @Model.Name) NewMetadata() Metadata {
+ md := Metadata{}
+ for k, v := range @(shortName).rawResponse.Header {
+ if len(k) > mdPrefixLen {
+ if prefix := k[0:mdPrefixLen]; strings.EqualFold(prefix, mdPrefix) {
+ md[strings.ToLower(k[mdPrefixLen:])] = v[0]
+ }
+ }
+ }
+ return md
+ }
+
+}
+
+@if (Model.IsDateTimeCustomHandlingRequired)
+{
+ var internalName = Model.Name.ToCamelCase();
+ var rec = Model.Name.ToString().ToShortName();
+ var local = $"{rec}2";
+
+ // MarshalXML implements the xml.Marshaler interface for @Model.Name.
+ func (@rec @Model.Name) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ if reflect.TypeOf((*@Model.Name)(nil)).Elem().Size() != reflect.TypeOf((*@internalName)(nil)).Elem().Size() {
+ panic("size mismatch between @Model.Name and @internalName")
+ }
+ @local := (*@internalName)(unsafe.Pointer(&@rec))
+ return e.EncodeElement(*@local, start)
+ }
+
+ // UnmarshalXML implements the xml.Unmarshaler interface for @Model.Name.
+ func (@rec *@Model.Name) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ if reflect.TypeOf((*@Model.Name)(nil)).Elem().Size() != reflect.TypeOf((*@internalName)(nil)).Elem().Size() {
+ panic("size mismatch between @Model.Name and @internalName")
+ }
+ @local := (*@internalName)(unsafe.Pointer(@rec))
+ return d.DecodeElement(@local, &start)
+ }
+
+}
\ No newline at end of file
diff --git a/src/Templates/ModelTemplate.cshtml b/src/Templates/ModelTemplate.cshtml
index 3f9575fc6..21aaa08ec 100644
--- a/src/Templates/ModelTemplate.cshtml
+++ b/src/Templates/ModelTemplate.cshtml
@@ -1,330 +1,225 @@
-@using AutoRest.Core.Model
-@using AutoRest.Core.Utilities
-@using AutoRest.Go
-@using AutoRest.Go.Model
-@using AutoRest.Go.Templates
-@using System.Linq
-
-@inherits AutoRest.Core.Template
-@{
- var shortName = Model.Name.ToString().ToShortName();
- var desc = $"{Model.Name} ...";
- if (!string.IsNullOrEmpty(Model.Documentation))
- {
- desc = $"{Model.Name} - {Model.Documentation}";
- }
-}
-
-@if (Model.IsPolymorphic)
-{
-
-type @(Model.Name) interface {
- @foreach (var dt in Model.DerivedTypes)
- {
- @:As@(dt.Name) () (*@(dt.Name), bool)
- }
-}
-
-@EmptyLine
-func unmarshal@(Model.Name)(body []byte) (@(Model.Name), error){
- var m map[string]interface{}
- err := json.Unmarshal(body, &m)
- if err != nil {
- return nil, err
- }
-@EmptyLine
- switch m["@(Model.PolymorphicDiscriminator)"] {
- @foreach (var dt in Model.DerivedTypes)
- {
-
- case string(@((dt as CompositeTypeGo).DiscriminatorEnumValue)):
- var @(dt.Name.FixedValue.ToShortName()) @(dt.Name)
- err := json.Unmarshal(body, &@(dt.Name.FixedValue.ToShortName()))
- return @(dt.Name.FixedValue.ToShortName()), err
-
- }
- default:
- return nil, errors.New("Unsupported type")
- }
-}
-
-func unmarshal@(Model.Name)Array(body []byte) ([]@(Model.Name), error){
- var rawMessages []*json.RawMessage
- err := json.Unmarshal(body, &rawMessages)
- if err != nil {
- return nil, err
- }
-@EmptyLine
- @(Model.Name.FixedValue.ToShortName())Array := make([]@(Model.Name), len(rawMessages))
-@EmptyLine
- for index, rawMessage := range rawMessages {
- @(Model.Name.FixedValue.ToShortName()), err := unmarshal@(Model.Name)(*rawMessage)
- if err != nil {
- return nil, err
- }
- @(Model.Name.FixedValue.ToShortName())Array[index] = @(Model.Name.FixedValue.ToShortName())
- }
- return @(Model.Name.FixedValue.ToShortName())Array, nil
-}
-
-}
-else
-{
-
-@WrapComment("// ", desc)
-type @Model.Name struct {
- @if (Model.IsResponseType)
- {
- @:rawResponse *http.Response
- }
-@(Model.Fields(false))
-}
-
-}
-
-@if (Model.BaseIsPolymorphic && !Model.IsPolymorphic)
-{
-
-@EmptyLine
-// MarshalJSON is the custom marshaler for @(Model.Name).
-func (@(Model.Name.FixedValue.ToShortName()) @(Model.Name))MarshalJSON() ([]byte, error){
- @(Model.Name.FixedValue.ToShortName()).@(Model.PolymorphicProperty) = @(Model.DiscriminatorEnumValue)
- type Alias @(Model.Name)
- return json.Marshal(&struct {
- Alias
- }{
- Alias: (Alias)(@(Model.Name.FixedValue.ToShortName())),
- })
-}
-
- @foreach (var st in Model.SiblingTypes)
- {
-
-@EmptyLine
-// As@(st.Name) is the @(Model.BaseModelType.Name) implementation for @(Model.Name).
-func (@(Model.Name.FixedValue.ToShortName()) @(Model.Name)) As@(st.Name)() (*@(st.Name), bool) {
- @if (st.Equals(Model))
- {
- @:return &@(Model.Name.FixedValue.ToShortName()), true
- }
- else
- {
- @:return nil, false
- }
-}
-
- }
-
-}
-
-@if (Model.HasPolymorphicFields && !Model.IsPolymorphic)
-{
-
-// UnmarshalJSON is the custom unmarshaler for @(Model.Name) struct.
-func (@(Model.Name.FixedValue.ToShortName()) *@(Model.Name)) UnmarshalJSON(body []byte) error {
- @if (Model.IsWrapperType)
- {
-
- @(Model.BaseType.Name.FixedValue.ToShortName()), err := unmarshal@(Model.BaseType.Name)(body)
- if err != nil {
- return err
- }
- @(Model.Name.FixedValue.ToShortName()).Value = @(Model.BaseType.Name.FixedValue.ToShortName())
-
- }
- else
- {
-
- var m map[string]*json.RawMessage
- err := json.Unmarshal(body, &m)
- if err != nil {
- return err
- }
-
- var v *json.RawMessage
- @foreach (var p in Model.AllProperties)
- {
-
- @EmptyLine
- v = m["@(p.SerializedName)"]
- if v != nil {
- @if (p.ModelType is CompositeType && (p.ModelType as CompositeTypeGo).IsPolymorphic)
- {
- @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@(p.ModelType.Name)(*m["@(p.SerializedName)"])
- }
- else if (p.ModelType is SequenceType && (p.ModelType as SequenceTypeGo).ElementType is CompositeType && ((p.ModelType as SequenceTypeGo).ElementType as CompositeType).IsPolymorphic)
- {
- @:@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)), err := unmarshal@((p.ModelType as SequenceTypeGo).ElementType.Name)Array(*m["@(p.SerializedName)"])
- }
- else
- {
-
- var @(CodeNamerGo.Instance.GetVariableName(p.SerializedName)) @(p.ModelType.Name)
- err = json.Unmarshal(*m["@(p.SerializedName)"], &@(CodeNamerGo.Instance.GetVariableName(p.SerializedName)))
-
- }
- if err != nil {
- return err
- }
- @if ((p.ModelType is CompositeType && (p.ModelType as CompositeTypeGo).IsPolymorphic) || (p.ModelType is EnumType))
- {
- @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = @(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
- }
- else
- {
- @:@(Model.Name.FixedValue.ToShortName()).@(p.Name) = &@(CodeNamerGo.Instance.GetVariableName(p.SerializedName))
- }
- }
-
- }
-
- }
-@EmptyLine
- return nil
-}
-
-}
-
-@EmptyLine
-@if (Model.IsResponseType)
-{
- var statusCodeFn = "StatusCode";
- var statusFn = "Status";
- if (Model.Properties.Where(p => p.Name == statusCodeFn).Any())
- {
- statusCodeFn = $"HTTP{statusCodeFn}";
- }
- if (Model.Properties.Where(p => p.Name == statusFn).Any())
- {
- statusFn = $"HTTP{statusFn}";
- }
-
-// Response returns the raw HTTP response object.
-func (@shortName @Model.Name) Response() *http.Response {
- return @(shortName).rawResponse
-}
-
-// @statusCodeFn returns the HTTP status code of the response, e.g. 200.
-func (@shortName @Model.Name) @(statusCodeFn)() int {
- return @(shortName).rawResponse.StatusCode
-}
-
-// @statusFn returns the HTTP status message of the response, e.g. "200 OK".
-func (@shortName @Model.Name) @(statusFn)() string {
- return @(shortName).rawResponse.Status
-}
-
- if (Model.IsStreamType())
- {
-
-
-// Body returns the raw HTTP response object's Body.
-func (@shortName @Model.Name) Body() io.ReadCloser {
- return @(shortName).rawResponse.Body
-}
-
- }
-}
-@EmptyLine
-@foreach (var headerResp in Model.ResponseHeaders())
-{
- var retSig = "string";
- var retExpr = $"{shortName}.rawResponse.Header.Get(\"{headerResp.Type.SerializedName}\")";
- if (headerResp.Type.ModelType.IsDateTimeType())
- {
- retSig = "time.Time";
- }
- else if (headerResp.Type.ModelType is EnumTypeGo)
- {
- retSig = headerResp.Type.ModelTypeName;
- retExpr = $"{headerResp.Type.ModelType.Name}({retExpr})";
- }
- else if (headerResp.Type.ModelType.IsETagType())
- {
- retSig = CodeNamerGo.Instance.ETagTypeName;
- retExpr = $"{CodeNamerGo.Instance.ETagTypeName}({retExpr})";
- }
- else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) || headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Long))
- {
- retSig = headerResp.Type.ModelTypeName;
- }
- else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.ByteArray))
- {
- retSig = "[]byte";
- }
-
-// @headerResp.Name returns the value for header @(headerResp.Type.SerializedName).
-func (@shortName @Model.Name) @(headerResp.Name)() @retSig {
-
- if (headerResp.Type.ModelType.IsDateTimeType())
- {
- var formatAs = "rfc3339Format";
- if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.DateTimeRfc1123))
- {
- formatAs = "time.RFC1123";
- }
-
- s := @retExpr
- if s == "" {
- return time.Time{}
- }
- t, err := time.Parse(@formatAs, s)
- if err != nil {
- panic(err)
- }
- return t
-
- }
- else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) || headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Long))
- {
- var bitSize = headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) ? "32" : "64";
-
- s := @retExpr
- if s == "" {
- return -1
- }
- i, err := strconv.ParseInt(s, 10, @bitSize)
- if err != nil {
- panic(err)
- }
- return @(headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) ? "int32(i)" : "i")
-
- }
- else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.ByteArray))
- {
-
- s := @retExpr
- if s == "" {
- return nil
- }
- b, err := base64.StdEncoding.DecodeString(s)
- if err != nil {
- panic(err)
- }
- return b
-
- }
- else
- {
- @:return @retExpr
- }
-@:}
-}
-
-@if (Model.ResponseIncludesMetadata)
-{
-
-// NewMetadata returns user-defined key/value pairs.
-func(@shortName @Model.Name) NewMetadata() Metadata {
- md := Metadata{}
- for k, v := range @(shortName).rawResponse.Header {
- if len(k) > mdPrefixLen {
- if prefix := k[0:mdPrefixLen]; strings.EqualFold(prefix, mdPrefix) {
- md[strings.ToLower(k[mdPrefixLen:])] = v[0]
- }
- }
- }
- return md
-}
-
-}
+@using AutoRest.Core.Model
+@using AutoRest.Core.Utilities
+@using AutoRest.Go
+@using AutoRest.Go.Model
+@using AutoRest.Go.Templates
+@using System.Linq
+@inherits AutoRest.Core.Template
+@{
+ var shortName = Model.Name.ToString().ToShortName();
+ var desc = $"{Model.Name} ...";
+ if (!string.IsNullOrEmpty(Model.Documentation))
+ {
+ desc = $"{Model.Name} - {Model.Documentation}";
+ }
+}
+@if (Model.HasInterface())
+{
+ @WrapComment("// ", $"{Model.GetInterfaceName()} {Model.Documentation.ToSentence()}")
+
+ type @(Model.GetInterfaceName()) interface {
+ @foreach (var dt in Model.DerivedTypes)
+ {
+ @:As@(dt.Name) () (*@(dt.Name), bool)
+ if (dt.HasInterface())
+ {
+ @:As@(dt.GetInterfaceName()) () (@(dt.GetInterfaceName()), bool)
+ }
+ }
+ As@(Model.Name) () (*@(Model.Name), bool)
+ }
+
+ @EmptyLine
+ @WrapComment("// ", $"{Model.Name} {Model.Documentation.ToSentence()}")
+ type @(Model.Name) struct {
+ @(Model.AddHTTPResponse())
+ @(Model.Fields(forMarshaller: false))
+ }
+
+}
+else
+{
+
+ @EmptyLine
+ @WrapComment("// ", desc)
+ type @Model.Name struct {
+ @if (Model.IsResponseType)
+ {
+ @:rawResponse *http.Response
+ }
+ @(Model.Fields(false))
+ }
+
+}
+
+@if (Model.BaseIsPolymorphic || Model.IsPolymorphic)
+{
+ foreach (var st in Model.SiblingTypes)
+ {
+
+ @EmptyLine
+ // As@(st.Name) is the @(Model.RootType.GetInterfaceName()) implementation for @(Model.Name).
+ func (@(Model.Name.FixedValue.ToShortName()) @(Model.Name)) As@(st.Name)() (*@(st.Name), bool) {
+ @if (st.Equals(Model))
+ {
+ @:return &@(Model.Name.FixedValue.ToShortName()), true
+ }
+ else
+ {
+ @:return nil, false
+ }
+ }
+ @if (st.HasInterface())
+ {
+ @EmptyLine
+ @:// As@(st.GetInterfaceName()) is the @(Model.RootType.GetInterfaceName()) implementation for @(Model.Name).
+ @:func(@(Model.Name.FixedValue.ToShortName()) @(Model.Name)) As@(st.GetInterfaceName())()(@(st.GetInterfaceName()), bool) {
+ if (st.Equals(Model) || Model.DerivesFrom(st))
+ {
+ @:return &@(Model.Name.FixedValue.ToShortName()), true
+ }
+ else
+ {
+ @:return nil, false
+ }
+ @:}
+ @EmptyLine
+ }
+
+ }
+}
+
+
+@if (Model.CodeModel.ShouldGenerateXmlSerialization)
+{
+ @(Include(new MarshallingXml(), Model))
+}
+else
+{
+ @(Include(new MarshallingJson(), Model))
+}
+
+@EmptyLine
+@if (Model.IsResponseType)
+{
+ var statusCodeFn = "StatusCode";
+ var statusFn = "Status";
+ if (Model.Properties.Any(p => p.Name == statusCodeFn))
+ {
+ statusCodeFn = $"HTTP{statusCodeFn}";
+ }
+ if (Model.Properties.Any(p => p.Name == statusFn))
+ {
+ statusFn = $"HTTP{statusFn}";
+ }
+
+ // Response returns the raw HTTP response object.
+ func (@shortName @Model.Name) Response() *http.Response {
+ return @(shortName).rawResponse
+ }
+
+ // @statusCodeFn returns the HTTP status code of the response, e.g. 200.
+ func (@shortName @Model.Name) @(statusCodeFn)() int {
+ return @(shortName).rawResponse.StatusCode
+ }
+
+ // @statusFn returns the HTTP status message of the response, e.g. "200 OK".
+ func (@shortName @Model.Name) @(statusFn)() string {
+ return @(shortName).rawResponse.Status
+ }
+
+ if (Model.IsStreamType())
+ {
+
+ // Body returns the raw HTTP response object's Body.
+ func (@shortName @Model.Name) Body() io.ReadCloser {
+ return @(shortName).rawResponse.Body
+ }
+
+ }
+}
+@EmptyLine
+@foreach (var headerResp in Model.ResponseHeaders())
+{
+ var retSig = "string";
+ var retExpr = $"{shortName}.rawResponse.Header.Get(\"{headerResp.Type.SerializedName}\")";
+ if (headerResp.Type.ModelType.IsDateTimeType())
+ {
+ retSig = "time.Time";
+ }
+ else if (headerResp.Type.ModelType is EnumTypeGo)
+ {
+ retSig = headerResp.Type.ModelTypeName;
+ retExpr = $"{headerResp.Type.ModelType.Name}({retExpr})";
+ }
+ else if (headerResp.Type.ModelType.IsETagType())
+ {
+ retSig = CodeNamerGo.Instance.ETagTypeName;
+ retExpr = $"{CodeNamerGo.Instance.ETagTypeName}({retExpr})";
+ }
+ else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) || headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Long))
+ {
+ retSig = headerResp.Type.ModelTypeName;
+ }
+ else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.ByteArray))
+ {
+ retSig = "[]byte";
+ }
+
+ // @headerResp.Name returns the value for header @(headerResp.Type.SerializedName).
+ func (@shortName @Model.Name) @(headerResp.Name)() @retSig {
+
+ if (headerResp.Type.ModelType.IsDateTimeType())
+ {
+ var formatAs = "rfc3339Format";
+ if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.DateTimeRfc1123))
+ {
+ formatAs = "time.RFC1123";
+ }
+
+ s := @retExpr
+ if s == "" {
+ return time.Time{}
+ }
+ t, err := time.Parse(@formatAs, s)
+ if err != nil {
+ panic(err)
+ }
+ return t
+
+ }
+ else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) || headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Long))
+ {
+ var bitSize = headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) ? "32" : "64";
+
+ s := @retExpr
+ if s == "" {
+ return -1
+ }
+ i, err := strconv.ParseInt(s, 10, @bitSize)
+ if err != nil {
+ panic(err)
+ }
+ return @(headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.Int) ? "int32(i)" : "i")
+
+ }
+ else if (headerResp.Type.ModelType.IsPrimaryType(KnownPrimaryType.ByteArray))
+ {
+
+ s := @retExpr
+ if s == "" {
+ return nil
+ }
+ b, err := base64.StdEncoding.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return b
+
+ }
+ else
+ {
+ @:return @retExpr
+ }
+ @:}
+}
diff --git a/src/Templates/ModelsTemplate.cshtml b/src/Templates/ModelsTemplate.cshtml
index b94a6768c..cc3c5cd36 100644
--- a/src/Templates/ModelsTemplate.cshtml
+++ b/src/Templates/ModelsTemplate.cshtml
@@ -1,128 +1,130 @@
-@using AutoRest.Core.Model
-@using AutoRest.Core.Utilities
-@using AutoRest.Go
-@using AutoRest.Go.Model
-@using AutoRest.Go.Templates
-@using System
-@using System.Collections.Generic
-@using System.Linq
-
-@inherits AutoRest.Core.Template
-
-package @Model.Namespace
-@EmptyLine
-@Header("// ")
-
-@EmptyLine
-
-@if (!Model.ModelImports.IsNullOrEmpty())
-{
-@:import (
-foreach (var import in Model.ModelImports)
-{
- @:@(import)
-}
-@:)
-@EmptyLine
-}
-
-@if (Model.UsesETags)
-{
-
-// @CodeNamerGo.Instance.ETagTypeName is an entity tag.
-type @CodeNamerGo.Instance.ETagTypeName string
-
-const (
- // ETagNone represents an empty entity tag.
- ETagNone @CodeNamerGo.Instance.ETagTypeName = ""
-@EmptyLine
- // ETagAny matches any entity tag.
- ETagAny @CodeNamerGo.Instance.ETagTypeName = "*"
-)
-
-}
-@if (Model.UsesMetadataType)
-{
-
-// Metadata contains metadata key/value pairs.
-type Metadata map[string]string
-@EmptyLine
-const mdPrefix = "x-ms-meta-"
-@EmptyLine
-const mdPrefixLen = len(mdPrefix)
-@EmptyLine
-// UnmarshalXML implements the xml.Unmarshaler interface for Metadata.
-func (md *Metadata) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- tokName := ""
-
- for t, err := d.Token(); err == nil; t, err = d.Token() {
- switch tt := t.(type) {
- case xml.StartElement:
- tokName = strings.ToLower(tt.Name.Local)
- break
- case xml.CharData:
- if *md == nil {
- *md = Metadata{}
- }
- (*md)[tokName] = string(tt)
-
- break
-
- }
- }
- return nil
-}
-
-}
-@if (Model.PagedTypes.Any())
-{
-
-// Marker represents an opaque value used in paged responses.
-type Marker struct {
- val *string
-}
-
-// NotDone returns true if the list enumeration should be started or is not yet complete. Specifically, NotDone returns true
-// for a just-initialized (zero value) Marker indicating that you should make an initial request to get a result portion from
-// the service. NotDone also returns true whenever the service returns an interim result portion. NotDone returns false only
-// after the service has returned the final result portion.
-func (m Marker) NotDone() bool {
- return m.val == nil || *m.val != ""
-}
-
-// UnmarshalXML implements the xml.Unmarshaler interface for Marker.
-func (m *Marker) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
- var out string
- err := d.DecodeElement(&out, &start)
- m.val = &out
- return err
-}
-
-}
-// concatenates a slice of const values with the specified separator between each item
-func joinConst(s interface{}, sep string) string {
- v := reflect.ValueOf(s)
- if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
- panic("s wasn't a slice or array")
- }
- ss := make([]string, 0, v.Len())
- for i := 0; i < v.Len(); i++ {
- ss = append(ss, v.Index(i).String())
- }
- return strings.Join(ss, sep)
-}
-@foreach (var e in Model.Enums)
-{
-
-@(Include(new EnumTemplate(), e))
-@EmptyLine
-
-}
-
-@foreach (var mt in Model.Models)
-{
-
-@(Include(new ModelTemplate(), mt))
-@EmptyLine
-
-}
+@using AutoRest.Core.Model
+@using AutoRest.Core.Utilities
+@using AutoRest.Go
+@using AutoRest.Go.Model
+@using AutoRest.Go.Templates
+@using System
+@using System.Collections.Generic
+@using System.Linq
+@inherits AutoRest.Core.Template
+package @Model.Namespace
+@EmptyLine
+@Header("// ")
+@EmptyLine
+@if (!Model.ModelImports.IsNullOrEmpty())
+{
+ @:import (
+foreach (var import in Model.ModelImports)
+ {
+ @:@(import)
+}
+ @:)
+ @EmptyLine
+}
+@if (Model.UsesETags)
+{
+
+ // @CodeNamerGo.Instance.ETagTypeName is an entity tag.
+ type @CodeNamerGo.Instance.ETagTypeName string
+
+ const (
+ // ETagNone represents an empty entity tag.
+ ETagNone @CodeNamerGo.Instance.ETagTypeName = ""
+ @EmptyLine
+ // ETagAny matches any entity tag.
+ ETagAny @CodeNamerGo.Instance.ETagTypeName = "*"
+ )
+
+}
+@if (Model.UsesMetadataType && Model.ShouldGenerateXmlSerialization)
+{
+
+ // Metadata contains metadata key/value pairs.
+ type Metadata map[string]string
+ @EmptyLine
+ const mdPrefix = "x-ms-meta-"
+ @EmptyLine
+ const mdPrefixLen = len(mdPrefix)
+ @EmptyLine
+ // UnmarshalXML implements the xml.Unmarshaler interface for Metadata.
+ func (md *Metadata) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ tokName := ""
+
+ for t, err := d.Token(); err == nil; t, err = d.Token() {
+ switch tt := t.(type) {
+ case xml.StartElement:
+ tokName = strings.ToLower(tt.Name.Local)
+ break
+ case xml.CharData:
+ if *md == nil {
+ *md = Metadata{}
+ }
+ (*md)[tokName] = string(tt)
+
+ break
+
+ }
+ }
+ return nil
+ }
+
+}
+
+@if (Model.PagedTypes.Any() && Model.ShouldGenerateXmlSerialization)
+{
+
+// Marker represents an opaque value used in paged responses.
+type Marker struct {
+ val *string
+}
+
+// NotDone returns true if the list enumeration should be started or is not yet complete. Specifically, NotDone returns true
+// for a just-initialized (zero value) Marker indicating that you should make an initial request to get a result portion from
+// the service. NotDone also returns true whenever the service returns an interim result portion. NotDone returns false only
+// after the service has returned the final result portion.
+func (m Marker) NotDone() bool {
+ return m.val == nil || *m.val != ""
+}
+
+// UnmarshalXML implements the xml.Unmarshaler interface for Marker.
+func (m *Marker) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ var out string
+ err := d.DecodeElement(&out, &start)
+ m.val = &out
+ return err
+}
+
+}
+
+// concatenates a slice of const values with the specified separator between each item
+func joinConst(s interface{}, sep string) string {
+ v := reflect.ValueOf(s)
+ if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
+ panic("s wasn't a slice or array")
+ }
+ ss := make([]string, 0, v.Len())
+ for i := 0; i < v.Len(); i++ {
+ ss = append(ss, v.Index(i).String())
+ }
+ return strings.Join(ss, sep)
+}
+@foreach (var e in Model.Enums)
+{
+
+ @(Include(new EnumTemplate(), e))
+ @EmptyLine
+
+}
+@foreach (var mt in Model.Models)
+{
+
+ @(Include(new ModelTemplate(), mt))
+ @EmptyLine
+
+}
+@if (Model.RequiresDateTimeCustomHandling.Any())
+{
+
+ @(Include(new Marshalling(), Model))
+
+}
diff --git a/src/TransformerGo.cs b/src/TransformerGo.cs
index 803d5decc..2060f2349 100644
--- a/src/TransformerGo.cs
+++ b/src/TransformerGo.cs
@@ -33,15 +33,34 @@ public override CodeModelGo TransformCodeModel(CodeModel cm)
SwaggerExtensions.ProcessGlobalParameters(cmg);
// Add the current package name as a reserved keyword
CodeNamerGo.Instance.ReserveNamespace(cm.Namespace);
- FixStutteringTypeNames(cmg);
TransformEnumTypes(cmg);
TransformModelTypes(cmg);
TransformMethods(cmg);
AzureExtensions.ProcessParameterizedHost(cmg);
+ FixStutteringTypeNames(cmg);
+ AssureUniqueNames(cmg);
+ TransformPropertyTypes(cmg);
return cmg;
}
+ private static void TransformPropertyTypes(CodeModelGo cmg)
+ {
+ foreach (var model in cmg.ModelTypes)
+ {
+ foreach (var property in model.Properties)
+ {
+ // Flattened fields are referred to with their type name,
+ // this name change generates correct custom unmarshalers and validation code,
+ // plus flattening does not need to be checked that often
+ if (property.ShouldBeFlattened() && property.ModelType is CompositeTypeGo)
+ {
+ property.Name = property.ModelType.HasInterface() ? property.ModelType.GetInterfaceName() : property.ModelType.Name.Value;
+ }
+ }
+ }
+ }
+
private void TransformEnumTypes(CodeModelGo cmg)
{
// fix up any enum types that are missing a name.
@@ -67,10 +86,17 @@ private void TransformEnumTypes(CodeModelGo cmg)
foreach (var et in cmg.EnumTypes)
{
var e = et as EnumTypeGo;
- var ev = new EnumValueGo();
- ev.Name = "None";
- ev.Description = $"{EnumValueGo.FormatName(e, ev)} represents an empty {e.Name}.";
+ var ev = new EnumValueGo
+ {
+ Name = "None"
+ };
+ ev.Description = $"represents an empty {e.Name}.";
e.Values.Add(ev);
+
+ foreach (var enumValue in et.Values)
+ {
+ enumValue.Name = EnumValueGo.FormatName((EnumTypeGo)et, (EnumValueGo)enumValue);
+ }
}
// And add any others with a defined name and value list (but not already located)
@@ -87,55 +113,121 @@ private void TransformEnumTypes(CodeModelGo cmg)
}
// Add discriminators
- foreach (var mt in cmg.ModelTypes)
+ // For all polymorphic types we need an enum with values for all the implementing types.
+ // To do this:
+ // 1. Create an enum with the basic type and all derived types as values.
+ // 2. Check if there is any enum already present that has the same name. If there is, check if it contains all the values of current enum.
+ // 3. If it has the same name and all values of current enum, use it. Otherwise create a new one and use it.
+ foreach (var mt in cmg.ModelTypes.Cast())
{
- if (mt.IsPolymorphic)
+ if (!mt.IsPolymorphic)
{
- var values = new List();
- foreach (var dt in (mt as CompositeTypeGo).DerivedTypes)
- {
- var ev = new EnumValueGo();
- ev.Name = string.Format("{0}{1}", CodeNamerGo.Instance.GetTypeName(mt.PolymorphicDiscriminator),
- CodeNamerGo.Instance.GetTypeName(dt.SerializedName));
- ev.SerializedName = dt.SerializedName;
- values.Add(ev);
- }
- bool nameAlreadyExists = cmg.EnumTypes.Any(et => et.Name.EqualsIgnoreCase(mt.PolymorphicDiscriminator));
- bool alreadyExists = nameAlreadyExists;
- if (nameAlreadyExists)
+ continue;
+ }
+
+ var enumValues = new List();
+
+ var typeName = $"{CodeNamerGo.Instance.GetTypeName(mt.PolymorphicDiscriminator)}";
+ if (typeName.EndsWith("Type"))
+ {
+ typeName = typeName.Substring(0, typeName.Length - 4);
+ }
+ var baseTypeEnumValue = new EnumValueGo
+ {
+ Name = $"{typeName}{CodeNamerGo.Instance.GetTypeName(mt.SerializedName)}",
+ SerializedName = mt.SerializedName
+ };
+
+ enumValues.Add(baseTypeEnumValue);
+
+ foreach (var dt in mt.DerivedTypes)
+ {
+ var ev = new EnumValueGo
{
- (mt as CompositeTypeGo).DiscriminatorEnum = cmg.EnumTypes.First(et => et.Name.EqualsIgnoreCase(mt.PolymorphicDiscriminator));
- var existingValues = new List();
- foreach (var v in cmg.EnumTypes.First(et => et.Name.EqualsIgnoreCase(mt.PolymorphicDiscriminator)).Values)
- {
- existingValues.Add(v.SerializedName);
- }
- foreach (var v in values)
- {
- if (!existingValues.Any(ev => ev.Equals(v.SerializedName)))
- {
- alreadyExists = false;
- }
- }
- }
- if (!alreadyExists)
+ Name = $"{typeName}{CodeNamerGo.Instance.GetTypeName(dt.SerializedName)}",
+ SerializedName = dt.SerializedName
+ };
+ enumValues.Add(ev);
+ }
+
+ var enumAlreadyExists = false;
+ var enumWithSameName = (EnumTypeGo)cmg.EnumTypes.FirstOrDefault(et => et.Name.EqualsIgnoreCase(CodeNamerGo.Instance.GetTypeName(mt.PolymorphicDiscriminator)));
+
+ if (enumWithSameName != null)
+ {
+ enumAlreadyExists = !enumValues.Select(value => value.SerializedName).Except(enumWithSameName.Values.Select(value => value.SerializedName)).Any();
+ }
+
+ if (enumAlreadyExists)
+ {
+ mt.DiscriminatorEnum = enumWithSameName;
+ }
+ else
+ {
+ mt.DiscriminatorEnum = cmg.Add(New(new
{
- (mt as CompositeTypeGo).DiscriminatorEnum = cmg.Add(New(new{
- Name = nameAlreadyExists ? string.Format("{0}{1}", mt.PolymorphicDiscriminator, mt.Name) : mt.PolymorphicDiscriminator,
- Values = values,
- }));
- }
+ Name = enumWithSameName == null ? mt.PolymorphicDiscriminator : $"{mt.PolymorphicDiscriminator}{mt.GetInterfaceName()}",
+ Values = enumValues,
+ })) as EnumTypeGo;
}
}
+ }
+ private static void AssureUniqueNames(CodeModelGo cmg)
+ {
// now normalize the names
// NOTE: this must be done after all enum types have been accounted for
foreach (var enumType in cmg.EnumTypes)
{
- enumType.SetName(CodeNamer.Instance.GetTypeName(enumType.Name.FixedValue));
+ enumType.SetName(CodeNamerGo.Instance.GetTypeName(enumType.Name));
foreach (var v in enumType.Values)
{
- v.Name = CodeNamer.Instance.GetEnumMemberName(v.Name);
+ v.Name = CodeNamerGo.Instance.GetEnumMemberName(v.Name);
+ }
+ }
+
+ // Ensure all enumerated type values have the simplest possible unique names
+ // -- The code assumes that all public type names are unique within the client and that the values
+ // of an enumerated type are unique within that type. To safely promote the enumerated value name
+ // to the top-level, it must not conflict with other existing types. If it does, prepending the
+ // value name with the (assumed to be unique) enumerated type name will make it unique.
+
+ // First, collect all type names (since these cannot change)
+ var topLevelNames = new HashSet();
+ foreach (var mt in cmg.ModelTypes)
+ {
+ topLevelNames.Add(mt.Name);
+ }
+
+ foreach (var em in cmg.EnumTypes)
+ {
+ topLevelNames.Add(em.Name);
+ }
+
+ // Then, note each enumerated type with one or more conflicting values and collect the values from
+ // those enumerated types without conflicts. do this on a sorted list to ensure consistent naming
+ foreach (var em in cmg.EnumTypes.Cast().OrderBy(etg => etg.Name.Value))
+ {
+ if (em.Values.Any(v => topLevelNames.Contains(v.Name) || CodeNamerGo.Instance.UserDefinedNames.Contains(v.Name)))
+ {
+ foreach (var v in em.Values)
+ {
+ v.Name = em.Name + v.Name;
+ }
+ }
+ else
+ {
+ topLevelNames.UnionWith(em.Values.Select(ev => ev.Name));
+ }
+ }
+
+ var modelList = new List();
+ foreach (var em in cmg.EnumTypes.OrderBy(etg => etg.Name.Value))
+ {
+ foreach (var v in em.Values)
+ {
+ v.Name = CodeNamerGo.Instance.GetUnique(v.Name, v, cmg.ModelTypes, modelList);
+ modelList.Add(v);
}
}
}
diff --git a/src/autorest.go.csproj b/src/autorest.go.csproj
index d59284713..c8990689f 100644
--- a/src/autorest.go.csproj
+++ b/src/autorest.go.csproj
@@ -1,4 +1,4 @@
-
+
# 2>nul || type %~df0|C:\Windows\system32\find.exe /v "setlocal"|C:\Windows\system32\find.exe /v "errorlevel"|powershell.exe -noninteractive -& exit %errorlevel% || #
@@ -74,5 +74,11 @@
All
+
+
+
+
+
+
diff --git a/test/src/tests/acceptancetests/stringgrouptest/body-string_test.go b/test/src/tests/acceptancetests/stringgrouptest/body-string_test.go
index 9ec0799e5..f7ad55724 100644
--- a/test/src/tests/acceptancetests/stringgrouptest/body-string_test.go
+++ b/test/src/tests/acceptancetests/stringgrouptest/body-string_test.go
@@ -43,14 +43,14 @@ const (
func (s *StringSuite) TestGetEmptyString(c *chk.C) {
str, err := stringClient.GetEmpty(context.Background())
c.Assert(err, chk.IsNil)
- c.Assert(*str.Value, chk.HasLen, 0)
- c.Assert(*str.Value, chk.Equals, emptyString)
+ c.Assert(str.Value, chk.HasLen, 0)
+ c.Assert(str.Value, chk.Equals, emptyString)
}
func (s *StringSuite) TestGetMbcs(c *chk.C) {
str, err := stringClient.GetMbcs(context.Background())
c.Assert(err, chk.IsNil)
- c.Assert(*str.Value, chk.Equals, multibyteBufferBody)
+ c.Assert(str.Value, chk.Equals, multibyteBufferBody)
}
func (s *StringSuite) TestGetNotProvided(c *chk.C) {
@@ -62,13 +62,13 @@ func (s *StringSuite) TestGetNotProvided(c *chk.C) {
func (s *StringSuite) TestGetNullString(c *chk.C) {
str, err := stringClient.GetNull(context.Background())
c.Assert(err, chk.IsNil)
- c.Assert(str.Value, chk.IsNil)
+ c.Assert(str.Value, chk.Equals, "")
}
func (s *StringSuite) TestGetWhitespace(c *chk.C) {
str, err := stringClient.GetWhitespace(context.Background())
c.Assert(err, chk.IsNil)
- c.Assert(*str.Value, chk.Equals, whitespaceText)
+ c.Assert(str.Value, chk.Equals, whitespaceText)
}
func (s *StringSuite) TestPutEmptyString(c *chk.C) {
@@ -124,7 +124,7 @@ func (s *StringSuite) TestPutWhitespace(c *chk.C) {
func (s *StringSuite) TestGetNotExpandable(c *chk.C) {
str, err := enumClient.GetNotExpandable(context.Background())
c.Assert(err, chk.IsNil)
- c.Assert(str.Value, chk.Equals, ColorsRedcolor)
+ c.Assert(str.Value, chk.Equals, Redcolor)
}
func (s *StringSuite) TestPutNotExpandable(c *chk.C) {
diff --git a/test/src/tests/generated/azurereport/version.go b/test/src/tests/generated/azurereport/version.go
index dc02e7eb1..a8b732d98 100644
--- a/test/src/tests/generated/azurereport/version.go
+++ b/test/src/tests/generated/azurereport/version.go
@@ -8,7 +8,7 @@ package azurereport
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-azurereport/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 azurereport/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/body-boolean/version.go b/test/src/tests/generated/body-boolean/version.go
index db560104e..9d1241100 100644
--- a/test/src/tests/generated/body-boolean/version.go
+++ b/test/src/tests/generated/body-boolean/version.go
@@ -8,7 +8,7 @@ package booleangroup
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-booleangroup/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 booleangroup/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/body-byte/version.go b/test/src/tests/generated/body-byte/version.go
index 170939dfb..deecde160 100644
--- a/test/src/tests/generated/body-byte/version.go
+++ b/test/src/tests/generated/body-byte/version.go
@@ -8,7 +8,7 @@ package bytegroup
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-bytegroup/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 bytegroup/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/body-integer/version.go b/test/src/tests/generated/body-integer/version.go
index d3fabe4b4..a4c873c14 100644
--- a/test/src/tests/generated/body-integer/version.go
+++ b/test/src/tests/generated/body-integer/version.go
@@ -8,7 +8,7 @@ package integergroup
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-integergroup/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 integergroup/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/body-string/models.go b/test/src/tests/generated/body-string/models.go
index 02feefbab..22a6f0091 100644
--- a/test/src/tests/generated/body-string/models.go
+++ b/test/src/tests/generated/body-string/models.go
@@ -25,7 +25,7 @@ func joinConst(s interface{}, sep string) string {
return strings.Join(ss, sep)
}
-// ColorsType enumerates the values for colors.
+// ColorsType enumerates the values for colors type.
type ColorsType string
const (
@@ -39,6 +39,11 @@ const (
ColorsRedcolor ColorsType = "red color"
)
+// PossibleColorsTypeValues returns an array of possible values for the ColorsType const type.
+func PossibleColorsTypeValues() []ColorsType {
+ return []ColorsType{ColorsBlueColor, ColorsGreenColor, ColorsNone, ColorsRedcolor}
+}
+
// Error ...
type Error struct {
Status *int32 `json:"status,omitempty"`
@@ -91,7 +96,7 @@ func (gb6er GetBase64URLEncodedResponse) Status() string {
type GetEmptyResponse struct {
rawResponse *http.Response
// Value - Possible values include: ''
- Value *string `json:"value,omitempty"`
+ Value string `json:"value,omitempty"`
}
// Response returns the raw HTTP response object.
@@ -113,7 +118,7 @@ func (ger GetEmptyResponse) Status() string {
type GetMbcsResponse struct {
rawResponse *http.Response
// Value - Possible values include: '啊齄丂狛狜隣郎隣兀﨩ˊ〞〡¦℡㈱‐ー﹡﹢﹫、〓ⅰⅹ⒈€㈠㈩ⅠⅫ! ̄ぁんァヶΑ︴АЯаяāɡㄅㄩ─╋︵﹄︻︱︳︴ⅰⅹɑɡ〇〾⿻⺁䜣€'
- Value *string `json:"value,omitempty"`
+ Value string `json:"value,omitempty"`
}
// Response returns the raw HTTP response object.
@@ -134,7 +139,7 @@ func (gmr GetMbcsResponse) Status() string {
// GetNotExpandableResponse ...
type GetNotExpandableResponse struct {
rawResponse *http.Response
- // Value - Possible values include: 'Redcolor', 'GreenColor', 'BlueColor', 'None'
+ // Value - Possible values include: 'ColorsRedcolor', 'ColorsGreenColor', 'ColorsBlueColor', 'ColorsNone'
Value ColorsType `json:"value,omitempty"`
}
@@ -199,7 +204,7 @@ func (gnb6er GetNullBase64URLEncodedResponse) Status() string {
type GetNullResponse struct {
rawResponse *http.Response
// Value - Possible values include: ''
- Value *string `json:"value,omitempty"`
+ Value string `json:"value,omitempty"`
}
// Response returns the raw HTTP response object.
@@ -220,7 +225,7 @@ func (gnr GetNullResponse) Status() string {
// GetReferencedResponse ...
type GetReferencedResponse struct {
rawResponse *http.Response
- // Value - Possible values include: 'Redcolor', 'GreenColor', 'BlueColor', 'None'
+ // Value - Possible values include: 'ColorsRedcolor', 'ColorsGreenColor', 'ColorsBlueColor', 'ColorsNone'
Value ColorsType `json:"value,omitempty"`
}
@@ -243,7 +248,7 @@ func (grr GetReferencedResponse) Status() string {
type GetWhitespaceResponse struct {
rawResponse *http.Response
// Value - Possible values include: ' Now is the time for all good men to come to the aid of their country '
- Value *string `json:"value,omitempty"`
+ Value string `json:"value,omitempty"`
}
// Response returns the raw HTTP response object.
diff --git a/test/src/tests/generated/body-string/version.go b/test/src/tests/generated/body-string/version.go
index 487be7747..ea37da1b3 100644
--- a/test/src/tests/generated/body-string/version.go
+++ b/test/src/tests/generated/body-string/version.go
@@ -8,7 +8,7 @@ package stringgroup
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-stringgroup/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 stringgroup/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/httpinfrastructure/models.go b/test/src/tests/generated/httpinfrastructure/models.go
index 41649eaa9..a8652ec00 100644
--- a/test/src/tests/generated/httpinfrastructure/models.go
+++ b/test/src/tests/generated/httpinfrastructure/models.go
@@ -70,18 +70,18 @@ type Error struct {
}
// Response returns the raw HTTP response object.
-func (e Error) Response() *http.Response {
- return e.rawResponse
+func (eVar Error) Response() *http.Response {
+ return eVar.rawResponse
}
// StatusCode returns the HTTP status code of the response, e.g. 200.
-func (e Error) StatusCode() int {
- return e.rawResponse.StatusCode
+func (eVar Error) StatusCode() int {
+ return eVar.rawResponse.StatusCode
}
// HTTPStatus returns the HTTP status message of the response, e.g. "200 OK".
-func (e Error) HTTPStatus() string {
- return e.rawResponse.Status
+func (eVar Error) HTTPStatus() string {
+ return eVar.rawResponse.Status
}
// Get200ModelA201ModelC404ModelDDefaultError200ValidResponse ...
diff --git a/test/src/tests/generated/httpinfrastructure/version.go b/test/src/tests/generated/httpinfrastructure/version.go
index 5aab890e7..15da85766 100644
--- a/test/src/tests/generated/httpinfrastructure/version.go
+++ b/test/src/tests/generated/httpinfrastructure/version.go
@@ -8,7 +8,7 @@ package httpinfrastructuregroup
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-httpinfrastructuregroup/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 httpinfrastructuregroup/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.
diff --git a/test/src/tests/generated/report/version.go b/test/src/tests/generated/report/version.go
index 8f3813734..c1fd411d4 100644
--- a/test/src/tests/generated/report/version.go
+++ b/test/src/tests/generated/report/version.go
@@ -8,7 +8,7 @@ package report
// UserAgent returns the UserAgent string to use when sending http.Requests.
func UserAgent() string {
- return "Azure-SDK-For-Go/0.0.0 arm-report/1.0.0"
+ return "Azure-SDK-For-Go/0.0.0 report/1.0.0"
}
// Version returns the semantic version (see http://semver.org) of the client.