Skip to content

Commit

Permalink
remove new dictionaryexpression and keep as snippet only (#3652)
Browse files Browse the repository at this point in the history
Fixes #3471
  • Loading branch information
m-nash authored Jun 25, 2024
1 parent 083739f commit 831e0c8
Show file tree
Hide file tree
Showing 20 changed files with 301 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,33 @@

namespace Microsoft.Generator.CSharp.Expressions
{
public sealed record DictionaryInitializerExpression(IReadOnlyList<(ValueExpression Key, ValueExpression Value)>? Values = null) : ValueExpression
public sealed record DictionaryInitializerExpression(IReadOnlyDictionary<ValueExpression, ValueExpression> Values) : ObjectInitializerExpression(Values)
{
internal override void Write(CodeWriter writer)
{
if (Values is not { Count: > 0 })
var enumerator = Values.GetEnumerator();
if (!enumerator.MoveNext())
{
writer.AppendRaw("{}");
writer.AppendRaw("{ }");
return;
}

writer.WriteLine();
writer.WriteRawLine("{");
for (int i = 0; i < Values.Count; i++)
using var scope = writer.Scope();
WriteItem(writer, enumerator.Current);
while (enumerator.MoveNext())
{
var (key, value) = Values[i];
key.Write(writer);
writer.AppendRaw(" = ");
value.Write(writer);
if (i < Values.Count - 1)
writer.WriteRawLine(",");
writer.WriteRawLine(",");
WriteItem(writer, enumerator.Current);
}
writer.WriteLine();
writer.AppendRaw("}");
}

private void WriteItem(CodeWriter writer, KeyValuePair<ValueExpression, ValueExpression> item)
{
writer.AppendRaw("{ ");
item.Key.Write(writer);
writer.AppendRaw(", ");
item.Value.Write(writer);
writer.AppendRaw(" }");
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,30 @@

namespace Microsoft.Generator.CSharp.Expressions
{
public sealed record NewInstanceExpression(CSharpType Type, IReadOnlyList<ValueExpression> Parameters, ObjectInitializerExpression? InitExpression = null) : ValueExpression
public sealed record NewInstanceExpression(CSharpType? Type, IReadOnlyList<ValueExpression> Parameters, ObjectInitializerExpression? InitExpression = null) : ValueExpression
{
private const int SingleLineParameterThreshold = 6;

internal override void Write(CodeWriter writer)
{
writer.Append($"new {Type}");
if (Parameters.Count > 0 || InitExpression is not { Parameters.Count: > 0 })
writer.Append($"new");
if (Type is not null)
writer.Append($" {Type}");
if (Parameters.Count > 0 || InitExpression is not { Values.Count: > 0 })
{
writer.WriteArguments(Parameters, Parameters.Count < SingleLineParameterThreshold);
}

if (InitExpression is { Parameters.Count: > 0 })
if (InitExpression is not null)
{
if (!InitExpression.UseSingleLine)
{
writer.WriteLine();
}
else
{
writer.AppendRaw(" ");
}
InitExpression.Write(writer);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,47 @@ namespace Microsoft.Generator.CSharp.Expressions
/// <summary>
/// Represents an object initializer expression.
/// </summary>
/// <param name="Parameters">The parameters to initialize the object to.</param>
/// <param name="Values">The set of property values to initialize the object to.</param>
/// <param name="UseSingleLine">Flag to determine if the object should be initialized inline.</param>
public sealed record ObjectInitializerExpression(IReadOnlyDictionary<string, ValueExpression>? Parameters = null, bool UseSingleLine = true) : ValueExpression
public record ObjectInitializerExpression(IReadOnlyDictionary<ValueExpression, ValueExpression> Values, bool UseSingleLine = false) : ValueExpression
{
internal override void Write(CodeWriter writer)
{
if (Parameters is not { Count: > 0 })
var iterator = Values.GetEnumerator();
if (!iterator.MoveNext())
{
writer.AppendRaw("{}");
writer.AppendRaw("{ }");
return;
}

if (UseSingleLine)
{
writer.AppendRaw("{");
var iterator = Parameters.GetEnumerator();
if (iterator.MoveNext())
writer.AppendRaw("{ ");
WriteItem(writer, iterator.Current);
while (iterator.MoveNext())
{
var (name, value) = iterator.Current;
writer.Append($"{name} = ");
value.Write(writer);
while (iterator.MoveNext())
{
writer.AppendRaw(", ");
(name, value) = iterator.Current;
writer.Append($"{name} = ");
value.Write(writer);
}
writer.AppendRaw(", ");
WriteItem(writer, iterator.Current);
}
writer.AppendRaw("}");
writer.AppendRaw(" }");
}
else
{
writer.WriteLine();
writer.WriteRawLine("{");
foreach (var (name, value) in Parameters)
using var scope = writer.Scope();
WriteItem(writer, iterator.Current);
while (iterator.MoveNext())
{
writer.Append($"{name} = ");
value.Write(writer);
writer.WriteRawLine(",");
WriteItem(writer, iterator.Current);
}

writer.AppendRaw("}");
writer.WriteLine();
}
}

private static void WriteItem(CodeWriter writer, KeyValuePair<ValueExpression, ValueExpression> item)
{
writer.Append($"{item.Key} = ");
item.Value.Write(writer);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ public static ValueExpression JsonException(ValueExpression message)
public static EnumerableSnippet Array(CSharpType? elementType, ValueExpression size) => new(elementType ?? typeof(object), new NewArrayExpression(elementType, Size: size));

public static DictionarySnippet Dictionary(CSharpType keyType, CSharpType valueType)
=> new(keyType, valueType, new NewDictionaryExpression(new CSharpType(typeof(Dictionary<,>), keyType, valueType)));
public static DictionarySnippet Dictionary(CSharpType keyType, CSharpType valueType, params (ValueExpression Key, ValueExpression Value)[] values)
=> new(keyType, valueType, new NewDictionaryExpression(new CSharpType(typeof(Dictionary<,>), keyType, valueType), new DictionaryInitializerExpression(values)));
=> new(keyType, valueType, new NewInstanceExpression(new CSharpType(typeof(Dictionary<,>), keyType, valueType), []));
public static DictionarySnippet Dictionary(CSharpType keyType, CSharpType valueType, IReadOnlyDictionary<ValueExpression, ValueExpression> values)
=> new(keyType, valueType, new NewInstanceExpression(new CSharpType(typeof(Dictionary<,>), keyType, valueType), [], new DictionaryInitializerExpression(values)));

public static TypedSnippet JsonSerializerOptions() => new FrameworkTypeSnippet(typeof(JsonSerializerOptions), new ValueExpression());

Expand All @@ -60,15 +60,15 @@ public static DictionarySnippet Dictionary(CSharpType keyType, CSharpType valueT
public static TimeSpanSnippet TimeSpan(int hours, int minutes, int seconds) => new(Instance(typeof(TimeSpan), Int(hours), Int(minutes), Int(seconds)));
public static TypedSnippet Uri(string uri) => Instance(typeof(Uri), Literal(uri));

public static ValueExpression Anonymous(string key, ValueExpression value) => Anonymous(new Dictionary<string, ValueExpression> { [key] = value });
public static ValueExpression Anonymous(IReadOnlyDictionary<string, ValueExpression>? properties) => new KeywordExpression("new", new ObjectInitializerExpression(properties, UseSingleLine: false));
public static ValueExpression Instance(ConstructorSignature ctorSignature, IReadOnlyList<ValueExpression> arguments, IReadOnlyDictionary<string, ValueExpression>? properties = null) => new NewInstanceExpression(ctorSignature.Type, arguments, properties != null ? new ObjectInitializerExpression(properties) : null);
public static ValueExpression Instance(ConstructorSignature ctorSignature, IReadOnlyDictionary<string, ValueExpression>? properties = null) => Instance(ctorSignature, ctorSignature.Parameters.Select(p => (ValueExpression)p).ToArray(), properties);
public static ValueExpression Anonymous(ValueExpression key, ValueExpression value) => Anonymous(new Dictionary<ValueExpression, ValueExpression> { [key] = value });
public static ValueExpression Anonymous(IReadOnlyDictionary<ValueExpression, ValueExpression> properties) => new NewInstanceExpression(null, [], new ObjectInitializerExpression(properties));
public static ValueExpression Instance(ConstructorSignature ctorSignature, IReadOnlyList<ValueExpression> arguments, IReadOnlyDictionary<ValueExpression, ValueExpression>? properties = null) => new NewInstanceExpression(ctorSignature.Type, arguments, properties != null ? new ObjectInitializerExpression(properties) : null);
public static ValueExpression Instance(ConstructorSignature ctorSignature, IReadOnlyDictionary<ValueExpression, ValueExpression>? properties = null) => Instance(ctorSignature, ctorSignature.Parameters.Select(p => (ValueExpression)p).ToArray(), properties);
public static ValueExpression Instance(CSharpType type, IReadOnlyList<ValueExpression> arguments) => new NewInstanceExpression(type, arguments);
public static ValueExpression Instance(CSharpType type, params ValueExpression[] arguments) => new NewInstanceExpression(type, arguments);
public static ValueExpression Instance(CSharpType type, IReadOnlyDictionary<string, ValueExpression> properties) => new NewInstanceExpression(type, System.Array.Empty<ValueExpression>(), new ObjectInitializerExpression(properties));
public static ValueExpression Instance(CSharpType type, IReadOnlyDictionary<ValueExpression, ValueExpression> properties) => new NewInstanceExpression(type, System.Array.Empty<ValueExpression>(), new ObjectInitializerExpression(properties));
public static TypedSnippet Instance(Type type, params ValueExpression[] arguments) => new FrameworkTypeSnippet(type, new NewInstanceExpression(type, arguments));
public static TypedSnippet Instance(Type type, IReadOnlyDictionary<string, ValueExpression> properties) => new FrameworkTypeSnippet(type, new NewInstanceExpression(type, System.Array.Empty<ValueExpression>(), new ObjectInitializerExpression(properties)));
public static TypedSnippet Instance(Type type, IReadOnlyDictionary<ValueExpression, ValueExpression> properties) => new FrameworkTypeSnippet(type, new NewInstanceExpression(type, System.Array.Empty<ValueExpression>(), new ObjectInitializerExpression(properties)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal override void Write(CodeWriter writer)
public static readonly MethodBodyStatement EmptyStatement = new();
public static readonly MethodBodyStatement EmptyLineStatement = new PrivateEmptyLineStatement();

public static ValueExpression Identifier(string name) => new MemberExpression(null, name);
public static ExtensibleSnippets Extensible => CodeModelPlugin.Instance.ExtensibleSnippets;
public static MethodBodyStatement AsStatement(this IEnumerable<MethodBodyStatement> statements) => statements.ToArray();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace Microsoft.Generator.CSharp.Tests.Expressions
{
internal class ExpressionsTest
internal class ExpressionsTests
{
private readonly string _mocksFolder = "Mocks";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using Microsoft.Generator.CSharp.Expressions;
using NUnit.Framework;
using static Microsoft.Generator.CSharp.Snippets.Snippet;


namespace Microsoft.Generator.CSharp.Tests.Expressions
{
public class NewDictionaryExpressionTests
{
[Test]
public void UseNewInstanceExpression()
{
var expression = new NewInstanceExpression(typeof(Dictionary<string, int>), [], new DictionaryInitializerExpression(new Dictionary<ValueExpression, ValueExpression>
{
{ Literal("x"), Literal(1) },
{ Literal("y"), Literal(2) }
}));
using CodeWriter writer = new();
expression.Write(writer);
var actual = writer.ToString(false);
Assert.AreEqual(Helpers.GetExpectedFromFile(), actual);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using Microsoft.Generator.CSharp.Expressions;
using NUnit.Framework;
using static Microsoft.Generator.CSharp.Snippets.Snippet;

namespace Microsoft.Generator.CSharp.Tests.Expressions
{
internal class NewInstanceExpressionTests
{
[Test]
public void ValidateAnonymousSingleLine()
{
using CodeWriter writer = new CodeWriter();
new NewInstanceExpression(null, [], new ObjectInitializerExpression(new Dictionary<ValueExpression, ValueExpression>
{
{ Identifier("key"), Literal(1) }
},
true)).Write(writer);
Assert.AreEqual("new { key = 1 }", writer.ToString(false));
}

[Test]
public void ValidateAnonymousWithPropertiesSingleLine()
{
using CodeWriter writer = new CodeWriter();
new NewInstanceExpression(null, [], new ObjectInitializerExpression(new Dictionary<ValueExpression, ValueExpression>
{
{ Identifier("key"), Literal(1) },
{ Identifier("value"), Literal(2) }
},
true)).Write(writer);
Assert.AreEqual("new { key = 1, value = 2 }", writer.ToString(false));
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
new global::System.Collections.Generic.Dictionary<string, int>
{
{ "x", 1 },
{ "y", 2 }
}
Loading

0 comments on commit 831e0c8

Please sign in to comment.