Add support to FormattableString to CodeWriter (#361)

* Add support to FormattableString to CodeWriter

* Fixes
This commit is contained in:
Pavel Krymets 2019-12-18 13:32:27 -08:00 коммит произвёл GitHub
Родитель d5ff3b3915
Коммит 628dab4815
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 260 добавлений и 282 удалений

Просмотреть файл

@ -186,7 +186,7 @@ namespace AutoRest.CSharp.V3.ClientModels
private static ConstantOrParameter[] ToParts(string httpRequestUri, Dictionary<string, ConstantOrParameter> parameters)
{
List<ConstantOrParameter> host = new List<ConstantOrParameter>();
foreach ((string text, bool isLiteral) in GetPathParts(httpRequestUri))
foreach ((string text, bool isLiteral) in StringExtensions.GetPathParts(httpRequestUri))
{
host.Add(isLiteral ? ClientModelBuilderHelpers.StringConstant(text) : parameters[text]);
}
@ -202,7 +202,7 @@ namespace AutoRest.CSharp.V3.ClientModels
}
List<PathSegment> host = new List<PathSegment>();
foreach ((string text, bool isLiteral) in GetPathParts(httpRequestUri))
foreach ((string text, bool isLiteral) in StringExtensions.GetPathParts(httpRequestUri))
{
if (!isLiteral)
{
@ -225,60 +225,6 @@ namespace AutoRest.CSharp.V3.ClientModels
private static int ToStatusCode(StatusCodes arg) => int.Parse(arg.ToString().Trim('_'));
//TODO: Refactor as this is written quite... ugly.
private static IEnumerable<(string Text, bool IsLiteral)> GetPathParts(string? path)
{
if (path == null)
{
yield break;
}
var index = 0;
var currentPart = new StringBuilder();
var innerPart = new StringBuilder();
while (index < path.Length)
{
if (path[index] == '{')
{
var innerIndex = index + 1;
while (innerIndex < path.Length)
{
if (path[innerIndex] == '}')
{
if (currentPart.Length > 0)
{
yield return (currentPart.ToString(), true);
currentPart.Clear();
}
yield return (innerPart.ToString(), false);
innerPart.Clear();
break;
}
innerPart.Append(path[innerIndex]);
innerIndex++;
}
if (innerPart.Length > 0)
{
currentPart.Append('{');
currentPart.Append(innerPart);
}
index = innerIndex + 1;
continue;
}
currentPart.Append(path[index]);
index++;
}
if (currentPart.Length > 0)
{
yield return (currentPart.ToString(), true);
}
}
private static RequestMethod? ToCoreRequestMethod(HttpMethod method) => method switch
{
HttpMethod.Delete => RequestMethod.Delete,

Просмотреть файл

@ -80,11 +80,11 @@ namespace AutoRest.CSharp.V3.CodeGen
writer.Line($"using var scope = clientDiagnostics.CreateScope(\"{@namespace.FullName}.{methodName}\");");
//TODO: Implement attribute logic
//writer.Line("scope.AddAttribute(\"key\", name);");
writer.Line("scope.Start();");
writer.Line($"scope.Start();");
using (writer.Try())
{
writer.Line("var request = pipeline.CreateRequest();");
writer.Line($"var request = pipeline.CreateRequest();");
var method = operation.Request.Method;
writer.Line($"request.Method = {writer.Type(typeof(RequestMethod))}.{method.ToRequestMethodName()};");
@ -119,10 +119,10 @@ namespace AutoRest.CSharp.V3.CodeGen
writer.ToSerializeCall(value.Type, body.Format, _typeFactory, w => WriteConstantOrParameter(w, value));
writer.Line("request.Content = content;");
writer.Line($"request.Content = content;");
}
writer.Line("var response = await pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);");
writer.Line($"var response = await pipeline.SendRequestAsync(request, cancellationToken).ConfigureAwait(false);");
WriteStatusCodeSwitch(writer, responseBody, headerModelType, operation);
}
@ -130,8 +130,8 @@ namespace AutoRest.CSharp.V3.CodeGen
var exceptionParameter = writer.Pair(typeof(Exception), "e");
using (writer.Catch(exceptionParameter))
{
writer.Line("scope.Failed(e);");
writer.Line("throw;");
writer.Line($"scope.Failed(e);");
writer.Line($"throw;");
}
}
}
@ -144,12 +144,12 @@ namespace AutoRest.CSharp.V3.CodeGen
}
else
{
writer.Append(constantOrParameter.Parameter.Name);
writer.AppendRaw(constantOrParameter.Parameter.Name);
var type = _typeFactory.CreateType(constantOrParameter.Type);
if (type.IsNullable && type.IsValueType)
{
writer.Append(".Value");
writer.Append($".Value");
}
}
}
@ -163,8 +163,7 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.If($"{parameter.Name} == null"))
{
writer.Append("throw new ").AppendType(typeof(ArgumentNullException)).Append("(nameof(").Append(parameter.Name).Append("));");
writer.Line();
writer.Line($"throw new {typeof(ArgumentNullException)}(nameof({parameter.Name}));");
}
}
}
@ -176,53 +175,28 @@ namespace AutoRest.CSharp.V3.CodeGen
if (constant.Value == null)
{
// Cast helps the overload resolution
writer.Append("(")
.AppendType(_typeFactory.CreateType(constant.Type))
.Append(")")
.Literal(null);
writer.Append($"({_typeFactory.CreateType(constant.Type)}){null:L}");
return;
}
switch (constant.Type)
{
case FrameworkTypeReference frameworkType when frameworkType.Type == typeof(DateTimeOffset):
var dateTimeValue = (DateTimeOffset)constant.Value;
dateTimeValue = dateTimeValue.ToUniversalTime();
writer.Append("new ");
writer.AppendType(typeof(DateTimeOffset));
writer.Append("(");
writer.Literal(dateTimeValue.Year);
writer.Comma();
writer.Literal(dateTimeValue.Month);
writer.Comma();
writer.Literal(dateTimeValue.Day);
writer.Comma();
writer.Literal(dateTimeValue.Hour);
writer.Comma();
writer.Literal(dateTimeValue.Minute);
writer.Comma();
writer.Literal(dateTimeValue.Second);
writer.Comma();
writer.Literal(dateTimeValue.Millisecond);
writer.Comma();
writer.AppendType(typeof(TimeSpan));
writer.Append(".");
writer.Append(nameof(TimeSpan.Zero));
writer.Append(")");
var d = (DateTimeOffset)constant.Value;
d = d.ToUniversalTime();
writer.Append($"new {typeof(DateTimeOffset)}({d.Year:L}, {d.Month:L}, {d.Day:L} ,{d.Hour:L}, {d.Minute:L}, {d.Second:L}, {d.Millisecond:L}, {typeof(TimeSpan)}.{nameof(TimeSpan.Zero)})");
break;
case FrameworkTypeReference _:
writer.Literal(constant.Value);
break;
case BinaryTypeReference _:
var value = (byte[])constant.Value;
writer.Append("new byte[] {");
writer.Append($"new byte[] {{");
foreach (byte b in value)
{
writer.Literal(b);
writer.Comma();
writer.Append($"{b}, ");
}
writer.Append("}");
writer.Append($"}}");
break;
default:
throw new InvalidOperationException("Unknown constant type");
@ -231,24 +205,20 @@ namespace AutoRest.CSharp.V3.CodeGen
private void WritePathSegment(CodeWriter writer, PathSegment segment)
{
writer.Append("request.Uri.AppendPath(");
writer.Append($"request.Uri.AppendPath(");
WriteConstantOrParameter(writer, segment.Value);
WriteSerializationFormat(writer, segment.Format);
writer.Comma();
writer.Literal(segment.Escape);
writer.Line(");");
writer.Line($", {segment.Escape:L});");
}
private void WriteHeader(CodeWriter writer, RequestHeader header)
{
using (WriteValueNullCheck(writer, header.Value))
{
writer.Append("request.Headers.Add(");
writer.Literal(header.Name);
writer.Comma();
writer.Append($"request.Headers.Add({header.Name:L}, ");
WriteConstantOrParameter(writer, header.Value);
WriteSerializationFormat(writer, header.Format);
writer.Line(");");
writer.Line($");");
}
}
@ -270,7 +240,7 @@ namespace AutoRest.CSharp.V3.CodeGen
var formatSpecifier = format.ToFormatSpecifier();
if (formatSpecifier != null)
{
writer.Comma().Literal(formatSpecifier);
writer.Append($", {formatSpecifier:L}");
}
}
@ -305,21 +275,14 @@ namespace AutoRest.CSharp.V3.CodeGen
ConstantOrParameter value = queryParameter.Value;
using (WriteValueNullCheck(writer, value))
{
writer.Append("request.Uri.");
writer.Append(method);
writer.Append("(");
writer.Literal(queryParameter.Name);
writer.Comma();
writer.Append($"request.Uri.{method}({queryParameter.Name:L}, ");
WriteConstantOrParameter(writer, value);
if (delimiter != null)
{
writer.Comma();
writer.Literal(delimiter);
writer.Append($", {delimiter:L}");
}
WriteSerializationFormat(writer, queryParameter.SerializationFormat);
writer.Comma();
writer.Literal(queryParameter.Escape);
writer.Line(");");
writer.Line($", {queryParameter.Escape:L});");
}
}
@ -339,45 +302,42 @@ namespace AutoRest.CSharp.V3.CodeGen
if (responseBody != null)
{
writer.Line($"using var document = await {writer.Type(typeof(JsonDocument))}.ParseAsync(response.ContentStream, default, cancellationToken).ConfigureAwait(false);");
writer.Append("var value = ");
writer.Append($"var value = ");
writer.ToDeserializeCall(
responseBody.Value,
responseBody.Format,
_typeFactory,
w => w.Append("document.RootElement")
w => w.Append($"document.RootElement")
);
writer.SemicolonLine();
writer.Line($";");
}
if (headersModelType != null)
{
writer.Append("var headers = new ")
.AppendType(headersModelType)
.Append("(response)")
.SemicolonLine();
writer.Line($"var headers = new {headersModelType}(response);");
}
switch (responseBody)
{
case null when headersModelType != null:
writer.Append($"return {writer.Type(typeof(ResponseWithHeaders))}.FromValue(headers, response);");
writer.Append($"return {typeof(ResponseWithHeaders)}.FromValue(headers, response);");
break;
case { } when headersModelType != null:
writer.Append($"return {writer.Type(typeof(ResponseWithHeaders))}.FromValue(value, headers, response);");
writer.Append($"return {typeof(ResponseWithHeaders)}.FromValue(value, headers, response);");
break;
case { }:
writer.Append($"return {writer.Type(typeof(Response))}.FromValue(value, response);");
writer.Append($"return {typeof(Response)}.FromValue(value, response);");
break;
case null:
writer.Append("return response;");
writer.Append($"return response;");
break;
}
}
writer.Line("default:");
writer.Line($"default:");
//TODO: Handle actual exception responses
writer.Line($"throw new {writer.Type(typeof(Exception))}();");
writer.Line($"throw new {typeof(Exception)}();");
}
}
}

Просмотреть файл

@ -21,7 +21,7 @@ namespace AutoRest.CSharp.V3.CodeGen
public CodeWriterScope Scope(string start = "{", string end = "}")
{
Line(start);
LineRaw(start);
return new CodeWriterScope(this, end);
}
@ -32,18 +32,77 @@ namespace AutoRest.CSharp.V3.CodeGen
return Scope();
}
public CodeWriter Append(FormattableString formattableString)
{
if (formattableString.ArgumentCount == 0)
{
return AppendRaw(formattableString.ToString());
}
const string literalFormatString = ":L";
foreach ((string Text, bool IsLiteral) part in StringExtensions.GetPathParts(formattableString.Format))
{
string text = part.Text;
if (part.IsLiteral)
{
AppendRaw(text);
continue;
}
var formatSeparatorIndex = text.IndexOf(':');
int index = int.Parse(formatSeparatorIndex == -1
? text.AsSpan()
: text.AsSpan(0, formatSeparatorIndex));
var argument = formattableString.GetArgument(index);
var isLiteral = text.EndsWith(literalFormatString);
switch (argument)
{
case CodeWriterDelegate d:
Append(d);
break;
case Type t:
AppendType(t);
break;
case CSharpType t:
AppendType(t);
break;
default:
if (isLiteral)
{
Literal(argument);
}
else
{
string? s = argument?.ToString();
if (s == null)
{
throw new ArgumentNullException(index.ToString());
}
AppendRaw(s);
}
break;
}
}
return this;
}
private string DefinitionLine(string? access, string? modifiers, string kind, string? name, string? implements = null) =>
new[] { access ?? _definitionAccessDefault, modifiers, kind, name , !string.IsNullOrWhiteSpace(implements)? $": {implements}" : null }.JoinIgnoreEmpty(" ");
private CodeWriterScope Definition(string? access, string? modifiers, string kind, string? name, string? implements = null)
{
Line(DefinitionLine(access, modifiers, kind, name, implements));
LineRaw(DefinitionLine(access, modifiers, kind, name, implements));
return Scope();
}
public CodeWriterScope Class(string? access, string? modifiers, string? name, string? implements = null)
{
Line(DefinitionLine(access, modifiers, "class", name, implements));
LineRaw(DefinitionLine(access, modifiers, "class", name, implements));
return Scope();
}
public CodeWriterScope Enum(string? access, string? modifiers, string? name, string? implements = null) => Definition(access, modifiers, "enum", name, implements);
@ -58,55 +117,55 @@ namespace AutoRest.CSharp.V3.CodeGen
public CodeWriterScope Method(string? modifiers, string? returnType, string? name, params string[] parameters)
{
Line(MethodDeclaration(modifiers, returnType, name, parameters));
LineRaw(MethodDeclaration(modifiers, returnType, name, parameters));
return Scope();
}
public CodeWriterScope Try()
{
Line("try");
Line($"try");
return Scope();
}
public CodeWriterScope Catch(params string[] parameters)
{
var parametersText = parameters.JoinIgnoreEmpty(", ");
Line($"catch{(parameters.Length > 0 ? $"({parametersText})" : String.Empty)}");
LineRaw($"catch{(parameters.Length > 0 ? $"({parametersText})" : String.Empty)}");
return Scope();
}
public CodeWriterScope If(string condition)
{
Line($"if({condition})");
LineRaw($"if({condition})");
return Scope();
}
public CodeWriterScope Else()
{
Line("else");
Line($"else");
return Scope();
}
public CodeWriterScope ForEach(string statement)
{
Line($"foreach({statement})");
LineRaw($"foreach({statement})");
return Scope();
}
public CodeWriterScope Switch(string value)
{
Line($"switch({value})");
LineRaw($"switch({value})");
return Scope();
}
public void MethodExpression(string modifiers, string? returnType, string name, string[]? parameters, string expression) =>
Line($"{MethodDeclaration(modifiers, returnType, name, parameters ?? new string[0])} => {expression};");
LineRaw($"{MethodDeclaration(modifiers, returnType, name, parameters ?? new string[0])} => {expression};");
public void EnumValue(string value, bool includeComma = true) =>
Line($"{value}{(includeComma ? "," : String.Empty)}");
LineRaw($"{value}{(includeComma ? "," : String.Empty)}");
public void AutoProperty(string modifiers, CSharpType type, string name, bool isReadOnly = false, string? initializer = null) =>
Line($"{modifiers} {Pair(type, name)} {{ get; {(isReadOnly ? "internal set; " : "set; ")}}}{initializer}");
LineRaw($"{modifiers} {Pair(type, name)} {{ get; {(isReadOnly ? "internal set; " : "set; ")}}}{initializer}");
public void UseNamespace(CSharpNamespace @namespace)
{
@ -141,12 +200,12 @@ namespace AutoRest.CSharp.V3.CodeGen
public CodeWriter AppendType(CSharpType type)
{
return Append(Type(type));
return AppendRaw(Type(type));
}
public CodeWriter AppendType(Type type, bool isNullable = false)
{
return Append(Type(type, isNullable));
return AppendRaw(Type(type, isNullable));
}
public string Type(Type type, bool isNullable = false) => Type(new CSharpType(type, isNullable));
@ -179,7 +238,7 @@ namespace AutoRest.CSharp.V3.CodeGen
public CodeWriter Literal(object? o)
{
return Append(o switch
return AppendRaw(o switch
{
null => "null",
string s => SyntaxFactory.Literal(s).ToString(),
@ -192,13 +251,26 @@ namespace AutoRest.CSharp.V3.CodeGen
});
}
public CodeWriter Line(string str = "")
public CodeWriter Line(FormattableString formattableString)
{
Append(formattableString);
Line();
return this;
}
public CodeWriter Line()
{
_builder.AppendLine();
return this;
}
public CodeWriter LineRaw(string str)
{
_builder.AppendLine(str);
return this;
}
public CodeWriter Append(string str)
public CodeWriter AppendRaw(string str)
{
_builder.Append(str);
return this;
@ -210,12 +282,6 @@ namespace AutoRest.CSharp.V3.CodeGen
return this;
}
public CodeWriter Comma() => Append(", ");
public CodeWriter Space() => Append(" ");
public CodeWriter SemicolonLine() => Append(";").Line();
public string ToFormattedCode()
{
if (_builder.Length == 0)
@ -272,7 +338,7 @@ namespace AutoRest.CSharp.V3.CodeGen
_end = end;
}
public void Dispose() => _writer?.Line(_end);
public void Dispose() => _writer?.LineRaw(_end);
}
}
}

Просмотреть файл

@ -76,23 +76,18 @@ namespace AutoRest.CSharp.V3.CodeGen
private static void WriteSerializeClientObject(CodeWriter writer, CodeWriterDelegate name, CSharpType type)
{
writer.AppendType(type.WithNullable(false))
.Append("Serializer.Serialize(")
.Append(name)
.Append(", writer)")
.SemicolonLine();
writer.Line($"{type.WithNullable(false)}Serializer.Serialize({name}, writer);");
}
private static void WriteSerializeClientEnum(CodeWriter writer, CodeWriterDelegate name, bool isNullable, bool isStringBased)
{
writer.Append("writer.WriteStringValue(");
writer.Append(name);
writer.Append($"writer.WriteStringValue({name}");
if (!isStringBased && isNullable)
{
writer.Append(".Value");
writer.Append($".Value");
}
writer.Append(isStringBased ? ".ToString()" : ".ToSerialString()");
writer.Line(");");
writer.AppendRaw(isStringBased ? ".ToString()" : ".ToSerialString()");
writer.Line($");");
}
private static void WriteSerializeSchemaTypeReference(CodeWriter writer, SchemaTypeReference type, TypeFactory typeFactory, CodeWriterDelegate name)
@ -106,22 +101,20 @@ namespace AutoRest.CSharp.V3.CodeGen
WriteSerializeClientEnum(writer, name, type.IsNullable, clientEnum.IsStringBased);
return;
default:
writer.Line("// Serialization of this type is not supported");
writer.Line($"// Serialization of this type is not supported");
return;
}
}
private static void WriteSerializeBinaryTypeReference(CodeWriter writer, CodeWriterDelegate name)
{
writer.Append("writer.WriteBase64StringValue(");
writer.Append(name);
writer.Line(");");
writer.Line($"writer.WriteBase64StringValue({name});");
}
private static void WriteSerializeDefault(CodeWriter writer, ClientTypeReference type, SerializationFormat format, TypeFactory typeFactory, CodeWriterDelegate name)
{
var frameworkType = typeFactory.CreateType(type)?.FrameworkType ?? typeof(void);
writer.Line(TypeSerializers[frameworkType](CodeWriter.Materialize(name), type.IsNullable, format) ?? "writer.WriteNullValue();");
writer.LineRaw(TypeSerializers[frameworkType](CodeWriter.Materialize(name), type.IsNullable, format) ?? "writer.WriteNullValue();");
}
public static void ToSerializeCall(this CodeWriter writer, ClientTypeReference type, SerializationFormat format, TypeFactory typeFactory, CodeWriterDelegate name, CodeWriterDelegate? serializedName = null)
@ -131,32 +124,30 @@ namespace AutoRest.CSharp.V3.CodeGen
if (serializedName != null)
{
writer.Append("writer.WritePropertyName(");
writer.Append(serializedName);
writer.Line(");");
writer.Line($"writer.WritePropertyName({serializedName});");
}
switch (type)
{
case CollectionTypeReference array:
{
writer.Line("writer.WriteStartArray();");
writer.Line($"writer.WriteStartArray();");
using (writer.ForEach($"var item in {CodeWriter.Materialize(name)}"))
{
writer.ToSerializeCall(array.ItemType, format, typeFactory, w => w.Append("item"));
writer.ToSerializeCall(array.ItemType, format, typeFactory, w => w.Append($"item"));
}
writer.Line("writer.WriteEndArray();");
writer.Line($"writer.WriteEndArray();");
return;
}
case DictionaryTypeReference dictionary:
{
writer.Line("writer.WriteStartObject();");
writer.Line($"writer.WriteStartObject();");
using (writer.ForEach($"var item in {CodeWriter.Materialize(name)}"))
{
writer.ToSerializeCall(dictionary.ValueType, format, typeFactory, w => w.Append("item.Value"), w => w.Append("item.Key"));
writer.ToSerializeCall(dictionary.ValueType, format, typeFactory, w => w.Append($"item.Value"), w => w.Append($"item.Key"));
}
writer.Line("writer.WriteEndObject();");
writer.Line($"writer.WriteEndObject();");
return;
}
@ -174,28 +165,18 @@ namespace AutoRest.CSharp.V3.CodeGen
private static void WriteDeserializeClientObject(CodeWriter writer, CSharpType cSharpType, CodeWriterDelegate name)
{
writer.AppendType(cSharpType)
.Append("Serializer.Deserialize(")
.Append(name)
.Append(")");
writer.Append($"{cSharpType}Serializer.Deserialize({name})");
}
private static void WriteDeserializeClientEnum(CodeWriter writer, CSharpType cSharpType, CodeWriterDelegate name, bool isStringBased)
{
if (isStringBased)
{
writer.Append("new ");
writer.AppendType(cSharpType);
writer.Append("(");
writer.Append(name);
writer.Append(".GetString())");
writer.Append($"new {cSharpType}({name}.GetString())");
return;
}
writer.Append(name);
writer.Append(".GetString().To");
writer.AppendType(cSharpType);
writer.Append("()");
writer.Append($"{name}.GetString().To{cSharpType}()");
}
private static void WriteDeserializeSchemaTypeReference(CodeWriter writer, CSharpType cSharpType, SchemaTypeReference type, TypeFactory typeFactory, CodeWriterDelegate name)
@ -209,21 +190,20 @@ namespace AutoRest.CSharp.V3.CodeGen
WriteDeserializeClientEnum(writer, cSharpType, name, clientEnum.IsStringBased);
return;
default:
writer.Append("/* Deserialization of this type is not supported */");
writer.Append($"/* Deserialization of this type is not supported */");
return;
}
}
private static void WriteDeserializeBinaryTypeReference(CodeWriter writer, CodeWriterDelegate name)
{
writer.Append(name);
writer.Append(".GetBytesFromBase64()");
writer.Append($"{name}.GetBytesFromBase64()");
}
private static void WriteDeserializeDefault(CodeWriter writer, CSharpType cSharpType, SerializationFormat format, CodeWriterDelegate name)
{
var frameworkType = cSharpType?.FrameworkType ?? typeof(void);
writer.Append(TypeDeserializers[frameworkType](CodeWriter.Materialize(name), format) ?? "null");
writer.AppendRaw(TypeDeserializers[frameworkType](CodeWriter.Materialize(name), format) ?? "null");
}
public static void ToDeserializeCall(this CodeWriter writer, ClientTypeReference type, SerializationFormat format, TypeFactory typeFactory, CodeWriterDelegate destination, CodeWriterDelegate element)
@ -237,10 +217,9 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.ForEach("var item in property.Value.EnumerateArray()"))
{
writer.Append(destination);
writer.Append(".Add(");
writer.ToDeserializeCall(array.ItemType, format, typeFactory, w => w.Append("item"));
writer.Line(");");
writer.Append($"{destination}.Add(");
writer.ToDeserializeCall(array.ItemType, format, typeFactory, w => w.Append($"item"));
writer.Line($");");
}
return;
@ -249,20 +228,18 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.ForEach("var item in property.Value.EnumerateObject()"))
{
writer.Append(destination);
writer.Append(".Add(item.Name, ");
writer.ToDeserializeCall(dictionary.ValueType, format, typeFactory, w => w.Append("item.Value"));
writer.Line(");");
writer.Append($"{destination}.Add(item.Name, ");
writer.ToDeserializeCall(dictionary.ValueType, format, typeFactory, w => w.Append($"item.Value"));
writer.Line($");");
}
return;
}
}
writer.Append(destination);
writer.Append("=");
writer.Append($"{destination} = ");
ToDeserializeCall(writer, type, format, typeFactory, element);
writer.SemicolonLine();
writer.Line($";");
}
public static void ToDeserializeCall(this CodeWriter writer, ClientTypeReference type, SerializationFormat format, TypeFactory typeFactory, CodeWriterDelegate element)

Просмотреть файл

@ -64,11 +64,7 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.Method("public", null, cs.Name))
{
writer
.Append(schema.Discriminator.Property)
.Append("=")
.Literal(schema.Discriminator.Value)
.SemicolonLine();
writer.Line($"{schema.Discriminator.Property} = {schema.Discriminator.Value:L};");
}
}
@ -95,29 +91,29 @@ namespace AutoRest.CSharp.V3.CodeGen
var iEnumerable = new CSharpType(typeof(IEnumerable));
string additionalProperties = "_additionalProperties";
writer.Append("private readonly ").AppendType(implementationType).Space().Append(additionalProperties).Append("= new ").AppendType(fieldType).Append("()").SemicolonLine();
writer.Line($"private readonly {implementationType} {additionalProperties} = new {fieldType}();");
writer.Append("public ").AppendType(iEnumeratorKeyValuePairType).Append(" GetEnumerator() => _additionalProperties.GetEnumerator();").Line()
.AppendType(iEnumerator).Space().AppendType(iEnumerable).Append(".GetEnumerator() => _additionalProperties.GetEnumerator();").Line()
.Append("public ").AppendType(iCollectionKeyType).Append(" Keys => _additionalProperties.Keys;").Line()
.Append("public ").AppendType(iCollectionItemType).Append(" Values => _additionalProperties.Values;").Line()
.Append("public bool TryGetValue(string key, out ").AppendType(itemType).Append(" value) => _additionalProperties.TryGetValue(key, out value);").Line()
.Append("public void Add(").AppendType(keyType).Append(" key, ").AppendType(itemType).Append(" value) => _additionalProperties.Add(key, value);").Line()
.Append("public bool ContainsKey(").AppendType(keyType).Append(" key) => _additionalProperties.ContainsKey(key);").Line()
.Append("public bool Remove(").AppendType(keyType).Append(" key) => _additionalProperties.Remove(key);").Line()
.Append("public int Count => _additionalProperties.Count;").Line()
.Append("bool ").AppendType(iCollectionKeyValuePairType).Append(".IsReadOnly => _additionalProperties.IsReadOnly;").Line()
.Append("void ").AppendType(iCollectionKeyValuePairType).Append(".Add(").AppendType(keyValuePairType).Append(" value) => _additionalProperties.Add(value);").Line()
.Append("bool ").AppendType(iCollectionKeyValuePairType).Append(".Remove(").AppendType(keyValuePairType).Append(" value) => _additionalProperties.Remove(value);").Line()
.Append("bool ").AppendType(iCollectionKeyValuePairType).Append(".Contains(").AppendType(keyValuePairType).Append(" value) => _additionalProperties.Contains(value);").Line()
.Append("void ").AppendType(iCollectionKeyValuePairType).Append(".CopyTo(").AppendType(keyValuePairType).Append("[] destination, int offset) => _additionalProperties.CopyTo(destination, offset);").Line()
.Append("void ").AppendType(iCollectionKeyValuePairType).Append(".Clear() => _additionalProperties.Clear();").Line();
writer.Line($"public {iEnumeratorKeyValuePairType} GetEnumerator() => {additionalProperties}.GetEnumerator();")
.Line($"{iEnumerator} {iEnumerable}.GetEnumerator() => {additionalProperties}.GetEnumerator();")
.Line($"public {iCollectionKeyType} Keys => {additionalProperties}.Keys;")
.Line($"public {iCollectionItemType} Values => {additionalProperties}.Values;")
.Line($"public bool TryGetValue(string key, out {itemType} value) => {additionalProperties}.TryGetValue(key, out value);")
.Line($"public void Add({keyType} key, {itemType} value) => {additionalProperties}.Add(key, value);")
.Line($"public bool ContainsKey({keyType} key) => {additionalProperties}.ContainsKey(key);")
.Line($"public bool Remove({keyType} key) => {additionalProperties}.Remove(key);")
.Line($"public int Count => _additionalProperties.Count;")
.Line($"bool {iCollectionKeyValuePairType}.IsReadOnly => {additionalProperties}.IsReadOnly;")
.Line($"void {iCollectionKeyValuePairType}.Add({keyValuePairType} value) => {additionalProperties}.Add(value);")
.Line($"bool {iCollectionKeyValuePairType}.Remove({keyValuePairType} value) => {additionalProperties}.Remove(value);")
.Line($"bool {iCollectionKeyValuePairType}.Contains({keyValuePairType} value) => {additionalProperties}.Contains(value);")
.Line($"void {iCollectionKeyValuePairType}.CopyTo({keyValuePairType}[] destination, int offset) => {additionalProperties}.CopyTo(destination, offset);")
.Line($"void {iCollectionKeyValuePairType}.Clear() => {additionalProperties}.Clear();");
using (writer.Append("public ").AppendType(itemType).Append(" this[").AppendType(keyType).Append(" key]").Scope())
using (writer.Append($"public {itemType} this[{keyType} key]").Scope())
{
writer
.Line("get => _additionalProperties[key];")
.Line("set => _additionalProperties[key] = value;");
.Line($"get => _additionalProperties[key];")
.Line($"set => _additionalProperties[key] = value;");
}
}
}
@ -150,24 +146,24 @@ namespace AutoRest.CSharp.V3.CodeGen
var nullableStringText = writer.Type(typeof(string), true);
var csTypeText = writer.Type(cs);
writer.Line($"private readonly {writer.Pair(nullableStringText, "_value")};");
writer.LineRaw($"private readonly {writer.Pair(nullableStringText, "_value")};");
writer.Line();
using (writer.Method("public", null, schema.CSharpName(), writer.Pair(stringText, "value")))
{
writer.Line($"_value = value ?? throw new {writer.Type(typeof(ArgumentNullException))}(nameof(value));");
writer.LineRaw($"_value = value ?? throw new {writer.Type(typeof(ArgumentNullException))}(nameof(value));");
}
writer.Line();
foreach (var choice in schema.Values.Select(c => c))
{
writer.Line($"private const {writer.Pair(stringText, $"{choice.Name}Value")} = \"{choice.Value.Value}\";");
writer.LineRaw($"private const {writer.Pair(stringText, $"{choice.Name}Value")} = \"{choice.Value.Value}\";");
}
writer.Line();
foreach (var choice in schema.Values)
{
writer.Line($"public static {writer.Pair(csTypeText, choice.Name)} {{ get; }} = new {csTypeText}({choice.Name}Value);");
writer.LineRaw($"public static {writer.Pair(csTypeText, choice.Name)} {{ get; }} = new {csTypeText}({choice.Name}Value);");
}
var boolText = writer.Type(typeof(bool));
@ -178,12 +174,12 @@ namespace AutoRest.CSharp.V3.CodeGen
writer.Line();
var editorBrowsableNever = $"[{writer.AttributeType(typeof(EditorBrowsableAttribute))}({writer.Type(typeof(EditorBrowsableState))}.Never)]";
writer.Line(editorBrowsableNever);
writer.LineRaw(editorBrowsableNever);
writer.MethodExpression("public override", boolText, "Equals", new[]{ writer.Pair(typeof(object), "obj", true)}, $"obj is {csTypeText} other && Equals(other)");
writer.MethodExpression("public", boolText, "Equals", new[] { writer.Pair(csTypeText, "other") }, $"{stringText}.Equals(_value, other._value, {writer.Type(typeof(StringComparison))}.Ordinal)");
writer.Line();
writer.Line(editorBrowsableNever);
writer.LineRaw(editorBrowsableNever);
writer.MethodExpression("public override", writer.Type(typeof(int)), "GetHashCode", null, "_value?.GetHashCode() ?? 0");
writer.MethodExpression("public override", nullableStringText, "ToString", null, "_value");
}

Просмотреть файл

@ -41,39 +41,21 @@ namespace AutoRest.CSharp.V3.CodeGen
private void WriteField(CodeWriter writer)
{
writer.Append("private readonly ")
.AppendType(typeof(Response))
.Space()
.Append(ResponseField)
.SemicolonLine();
writer.Line($"private readonly {typeof(Response)} {ResponseField};");
}
private void WriteConstructor(CodeWriter writer, CSharpType cs)
{
using (writer.Method("public", null, cs.Name, writer.Pair(typeof(Response), ResponseParameter)))
{
writer.Append(ResponseField)
.Append("=")
.Append(ResponseParameter)
.SemicolonLine();
writer.Line($"{ResponseField} = {ResponseParameter};");
}
}
private void WriteHeaderProperty(CodeWriter writer, ResponseHeader header)
{
var type = _typeFactory.CreateType(header.Type);
writer.Append("public ")
.AppendType(type)
.Space()
.Append(header.Name)
.Append("=>")
.Append(ResponseField)
.Append(".Headers.TryGetValue(")
.Literal(header.SerializedName)
.Append(", out ")
.AppendType(type)
.Append(" value) ? value : null")
.SemicolonLine();
writer.Line($"public {type} {header.Name} => {ResponseField}.Headers.TryGetValue({header.SerializedName:L}, out {type} value) ? value : null;");
}
}
}

Просмотреть файл

@ -45,7 +45,7 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.If($"property.Value.ValueKind == {writer.Type(typeof(JsonValueKind))}.Null"))
{
writer.Append("continue;");
writer.Append($"continue;");
}
}
@ -53,8 +53,7 @@ namespace AutoRest.CSharp.V3.CodeGen
{
if (propertyType.IsNullable && (type is DictionaryTypeReference || type is CollectionTypeReference))
{
writer.Append($"result.{name} = new {writer.Type(_typeFactory.CreateConcreteType(property.Type))}()")
.SemicolonLine();
writer.Line($"result.{name} = new {writer.Type(_typeFactory.CreateConcreteType(property.Type))}();");
}
}
@ -65,7 +64,7 @@ namespace AutoRest.CSharp.V3.CodeGen
WriteInitialization();
writer.ToDeserializeCall(type, format, _typeFactory, w=> w.Append($"result.{name}"), w => w.Append("property.Value"));
writer.ToDeserializeCall(type, format, _typeFactory, w=> w.Append($"result.{name}"), w => w.Append($"property.Value"));
}
@ -94,18 +93,15 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.If($"element.TryGetProperty(\"{model.Discriminator.SerializedName}\", out {writer.Type(typeof(JsonElement))} discriminator)"))
{
writer.Line("switch (discriminator.GetString())");
writer.Line($"switch (discriminator.GetString())");
using (writer.Scope())
{
foreach (var implementation in model.Discriminator.Implementations)
{
writer
.Append("case ")
.Literal(implementation.Key)
.Append(": return ")
.ToDeserializeCall(implementation.Type, SerializationFormat.Default, _typeFactory,
w => w.Append("element"));
writer.SemicolonLine();
.Append($"case {implementation.Key:L}: return ")
.ToDeserializeCall(implementation.Type, SerializationFormat.Default, _typeFactory, w => w.Append($"element"));
writer.Line($";");
}
}
}
@ -123,7 +119,7 @@ namespace AutoRest.CSharp.V3.CodeGen
using (writer.If($"property.NameEquals(\"{property.SerializedName}\")"))
{
ReadProperty(writer, property);
writer.Line("continue;");
writer.Line($"continue;");
}
}
@ -132,14 +128,14 @@ namespace AutoRest.CSharp.V3.CodeGen
if (implementsDictionary != null)
{
writer.Append("result.Add(property.Name, ");
writer.ToDeserializeCall(implementsDictionary.ValueType, SerializationFormat.Default, _typeFactory, w => w.Append("property.Value"));
writer.Append(");").Line();
writer.Append($"result.Add(property.Name, ");
writer.ToDeserializeCall(implementsDictionary.ValueType, SerializationFormat.Default, _typeFactory, w => w.Append($"property.Value"));
writer.Line($");");
}
}
writer.Line("return result;");
writer.Line($"return result;");
}
}
@ -166,7 +162,7 @@ namespace AutoRest.CSharp.V3.CodeGen
{
if (model.Discriminator?.HasDirectDescendants == true)
{
writer.Line("switch (model)");
writer.Line($"switch (model)");
using (writer.Scope())
{
foreach (var implementation in model.Discriminator.Implementations)
@ -178,15 +174,15 @@ namespace AutoRest.CSharp.V3.CodeGen
var type = _typeFactory.CreateType(implementation.Type);
var localName = type.Name.ToVariableName();
writer.Append("case ").AppendType(type).Space().Append(localName).Append(":").Line();
writer.Line($"case {type} {localName}:");
writer.ToSerializeCall(implementation.Type, SerializationFormat.Default, _typeFactory,
w => w.Append(localName));
writer.Line("return;");
w => w.AppendRaw(localName));
writer.Line($"return;");
}
}
}
writer.Line("writer.WriteStartObject();");
writer.Line($"writer.WriteStartObject();");
DictionaryTypeReference? implementsDictionary = null;
@ -200,7 +196,7 @@ namespace AutoRest.CSharp.V3.CodeGen
property.Type,
property.Format,
_typeFactory,
w => w.Append("model.").Append(property.Name),
w => w.Append($"model.{property.Name}"),
w => w.Literal(property.SerializedName));
}
@ -212,11 +208,11 @@ namespace AutoRest.CSharp.V3.CodeGen
{
using (writer.ForEach("var item in model"))
{
writer.ToSerializeCall(implementsDictionary.ValueType, SerializationFormat.Default, _typeFactory, w => w.Append("item.Value"), w => w.Append("item.Key"));
writer.ToSerializeCall(implementsDictionary.ValueType, SerializationFormat.Default, _typeFactory, w => w.Append($"item.Value"), w => w.Append($"item.Key"));
}
}
writer.Line("writer.WriteEndObject();");
writer.Line($"writer.WriteEndObject();");
}
}

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using CaseExtensions;
@ -27,5 +28,59 @@ namespace AutoRest.CSharp.V3.Utilities
public static string? ToCleanName(this string? name) => name?.ToPascalCase().RemoveNonWordCharacters().PrependUnderscoreIfNumbers();
[return: NotNullIfNotNull("name")]
public static string? ToVariableName(this string? name) => name?.ToCamelCase().RemoveNonWordCharacters().PrependUnderscoreIfNumbers();
public static IEnumerable<(string Text, bool IsLiteral)> GetPathParts(string? path)
{
if (path == null)
{
yield break;
}
var index = 0;
var currentPart = new StringBuilder();
var innerPart = new StringBuilder();
while (index < path.Length)
{
if (path[index] == '{')
{
var innerIndex = index + 1;
while (innerIndex < path.Length)
{
if (path[innerIndex] == '}')
{
if (currentPart.Length > 0)
{
yield return (currentPart.ToString(), true);
currentPart.Clear();
}
yield return (innerPart.ToString(), false);
innerPart.Clear();
break;
}
innerPart.Append(path[innerIndex]);
innerIndex++;
}
if (innerPart.Length > 0)
{
currentPart.Append('{');
currentPart.Append(innerPart);
}
index = innerIndex + 1;
continue;
}
currentPart.Append(path[index]);
index++;
}
if (currentPart.Length > 0)
{
yield return (currentPart.ToString(), true);
}
}
}
}