Skip to content

Commit

Permalink
Add Frozen Collections (NET80) (#17)
Browse files Browse the repository at this point in the history
* Add Frozen Collections (NET80)

* remove editorconfig

* unify code
  • Loading branch information
ycherkes authored Dec 10, 2023
1 parent afa3565 commit c74de34
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VarDump is a utility for serialization runtime objects to C# or Visual Basic str

Developed as a free alternative of [ObjectDumper.NET](https://github.com/thomasgalliker/ObjectDumper), which is not free for commercial use.

[![nuget version](https://img.shields.io/badge/Nuget-v0.2.7-blue)](https://www.nuget.org/packages/VarDump)
[![nuget version](https://img.shields.io/badge/Nuget-v0.2.8-blue)](https://www.nuget.org/packages/VarDump)
[![nuget downloads](https://img.shields.io/nuget/dt/VarDump?label=Downloads)](https://www.nuget.org/packages/VarDump)

# Powered By
Expand Down
2 changes: 1 addition & 1 deletion VarDump.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VarDump", "src\VarDump.csproj", "{ED778772-EC95-4362-8C3C-C2DFF8F0ABD6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{6CDE3AAC-4726-438B-8D09-51ED6434BF68}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{6CDE3AAC-4726-438B-8D09-51ED6434BF68}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
5 changes: 5 additions & 0 deletions src/CSharpDumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public string Dump(object obj)

public void Dump(object obj, TextWriter textWriter)
{
if (textWriter == null)
{
throw new ArgumentNullException(nameof(textWriter));
}

DumpImpl(obj, textWriter);
}

Expand Down
20 changes: 18 additions & 2 deletions src/Utils/ReflectionUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,27 @@ public static bool IsGenericCollection(this Type type)
return hasICollection;
}

public static bool IsPublicImmutableCollection(this Type type)
public static bool IsPublicImmutableOrFrozenCollection(this Type type)
{
var typeFullName = type.FullName ?? "";

return type.IsPublic && typeFullName.StartsWith("System.Collections.Immutable");
return type.IsPublic && typeFullName.StartsWith("System.Collections.Immutable") || IsFrozenCollection(typeFullName);
}

private static bool IsFrozenCollection(string typeFullName)
{
return typeFullName.StartsWith("System.Collections.Frozen");
}

public static string GetImmutableOrFrozenTypeName(this Type type)
{
var typeFullName = type.FullName;
var typeName = type.Name;
if (IsFrozenCollection(typeFullName))
{
typeName = typeName.Substring(typeName.IndexOf("Frozen", StringComparison.Ordinal));
}
return typeName.Split('`')[0];
}

public static bool IsReadonlyCollection(this Type type)
Expand Down
6 changes: 3 additions & 3 deletions src/VarDump.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<AssemblyName>VarDump</AssemblyName>
<AssemblyVersion>0.2.7</AssemblyVersion>
<FileVersion>0.2.7</FileVersion>
<AssemblyVersion>0.2.8</AssemblyVersion>
<FileVersion>0.2.8</FileVersion>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<Copyright>Copyright $([System.DateTime]::Now.Year) Yevhen Cherkes</Copyright>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>VarDump</Title>
<Version>0.2.7</Version>
<Version>0.2.8</Version>
<Description>VarDump is a utility for serialization runtime objects to C# and Visual Basic string.</Description>
<PackageProjectUrl>https://github.com/ycherkes/VarDump</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand Down
14 changes: 7 additions & 7 deletions src/Visitor/KnownTypes/CollectionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,20 @@ private CodeExpression VisitSimpleCollection(IEnumerable enumerable, Type elemen

var type = enumerable.GetType();

var isImmutable = type.IsPublicImmutableCollection();
var isImmutableOrFrozen = type.IsPublicImmutableOrFrozenCollection();

if (type.IsArray || isImmutable || !IsCollection(enumerable))
if (type.IsArray || isImmutableOrFrozen || !IsCollection(enumerable))
{
if (type.IsArray && ((Array)enumerable).Rank > 1)
{
items = ChunkMultiDimensionalArrayExpression((Array)enumerable, items);
}

CodeExpression expr = new CodeArrayCreateExpression(
new CodeTypeReference(isImmutable || !type.IsPublic ? elementType.MakeArrayType() : type, _typeReferenceOptions),
new CodeTypeReference(isImmutableOrFrozen || !type.IsPublic ? elementType.MakeArrayType() : type, _typeReferenceOptions),
items.ToArray());

if (isImmutable) expr = new CodeMethodInvokeExpression(expr, $"To{type.Name.Split('`')[0]}");
if (isImmutableOrFrozen) expr = new CodeMethodInvokeExpression(expr, $"To{type.GetImmutableOrFrozenTypeName()}");

return expr;
}
Expand Down Expand Up @@ -155,7 +155,7 @@ private CodeExpression VisitAnonymousCollection(IEnumerable enumerable)
var items = enumerable.Cast<object>().Select(_rootObjectVisitor.Visit);
var type = enumerable.GetType();

var isImmutable = type.IsPublicImmutableCollection();
var isImmutableOrFrozen = type.IsPublicImmutableOrFrozenCollection();

var typeReference = new CodeAnonymousTypeReference { ArrayRank = 1 };

Expand All @@ -169,8 +169,8 @@ private CodeExpression VisitAnonymousCollection(IEnumerable enumerable)
typeReference,
items.ToArray());

if (isImmutable || enumerable is IList && !type.IsArray)
expr = new CodeMethodInvokeExpression(expr, $"To{type.Name.Split('`')[0]}");
if (isImmutableOrFrozen || enumerable is IList && !type.IsArray)
expr = new CodeMethodInvokeExpression(expr, $"To{type.GetImmutableOrFrozenTypeName()}");

return expr;
}
Expand Down
12 changes: 6 additions & 6 deletions src/Visitor/KnownTypes/DictionaryVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ private CodeExpression VisitSimpleDictionary(IDictionary dict)
var items = dict.Cast<object>().Select(VisitKeyValuePairGenerateImplicitly);

var type = dict.GetType();
var isImmutable = type.IsPublicImmutableCollection();
var isImmutableOrFrozen = type.IsPublicImmutableOrFrozenCollection();

if (isImmutable)
if (isImmutableOrFrozen)
{
var keyType = ReflectionUtils.GetInnerElementType(dict.Keys.GetType());
var valueType = ReflectionUtils.GetInnerElementType(dict.Values.GetType());
Expand All @@ -70,7 +70,7 @@ private CodeExpression VisitSimpleDictionary(IDictionary dict)

CodeExpression dictionaryCreateExpression = new CodeObjectCreateAndInitializeExpression(new CodeCollectionTypeReference(dictionaryType, _typeReferenceOptions), items);

dictionaryCreateExpression = new CodeMethodInvokeExpression(dictionaryCreateExpression, $"To{type.Name.Split('`')[0]}");
dictionaryCreateExpression = new CodeMethodInvokeExpression(dictionaryCreateExpression, $"To{type.GetImmutableOrFrozenTypeName()}");

return dictionaryCreateExpression;
}
Expand All @@ -94,10 +94,10 @@ private CodeExpression VisitAnonymousDictionary(IEnumerable dictionary)
var keyLambdaExpression = new CodeLambdaExpression(new CodePropertyReferenceExpression(variableReferenceExpression, keyName), variableReferenceExpression);
var valueLambdaExpression = new CodeLambdaExpression(new CodePropertyReferenceExpression(variableReferenceExpression, valueName), variableReferenceExpression);

var isImmutable = type.IsPublicImmutableCollection();
var isImmutableOrFrozen = type.IsPublicImmutableOrFrozenCollection();

expr = isImmutable
? new CodeMethodInvokeExpression(expr, $"To{type.Name.Split('`')[0]}", keyLambdaExpression, valueLambdaExpression)
expr = isImmutableOrFrozen
? new CodeMethodInvokeExpression(expr, $"To{type.GetImmutableOrFrozenTypeName()}", keyLambdaExpression, valueLambdaExpression)
: new CodeMethodInvokeExpression(expr, "ToDictionary", keyLambdaExpression, valueLambdaExpression);

return expr;
Expand Down
5 changes: 5 additions & 0 deletions src/VisualBasicDumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public string Dump(object obj)

public void Dump(object obj, TextWriter textWriter)
{
if(textWriter == null)
{
throw new ArgumentNullException(nameof(textWriter));
}

DumpImpl(obj, textWriter);
}

Expand Down
6 changes: 5 additions & 1 deletion test/UnitTests/DataTableSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

namespace UnitTests;

#if !NET8_0_OR_GREATER

public class DataTableSpec
{
[Fact(Skip = "Skip")]
Expand Down Expand Up @@ -68,4 +70,6 @@ public void DumpDataTableCsharp()

Assert.Equal(@"", result);
}
}
}

#endif
97 changes: 97 additions & 0 deletions test/UnitTests/FrozenCollectionsNet8Spec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#if NET8_0_OR_GREATER

using System.Collections.Frozen;
using System.Collections.Generic;
using VarDump;
using Xunit;

namespace UnitTests
{
public class FrozenCollectionsNet8Spec
{

[Fact]
public void DumpFrozenSetCsharp()
{
FrozenSet<int> frozenSet = new[] { 1 }.ToFrozenSet();

var dumper = new CSharpDumper();

var result = dumper.Dump(frozenSet);

Assert.Equal("""
var smallValueTypeComparableFrozenSetOfInt = new int[]
{
1
}.ToFrozenSet();
""", result);
}

[Fact]
public void DumpFrozenSetVb()
{
FrozenSet<int> frozenSet = new[] { 1 }.ToFrozenSet();

var dumper = new VisualBasicDumper();

var result = dumper.Dump(frozenSet);

Assert.Equal("""
Dim smallValueTypeComparableFrozenSetOfInteger = New Integer(){
1
}.ToFrozenSet()
""", result);
}

[Fact]
public void DumpFrozenDictionaryCsharp()
{
var frozenDictionary = new Dictionary<string, string>
{
{ "Steeve", "Test reference" }
}.ToFrozenDictionary();

var dumper = new CSharpDumper();

var result = dumper.Dump(frozenDictionary);

Assert.Equal("""
var lengthBucketsFrozenDictionaryOfString = new Dictionary<string, string>
{
{
"Steeve",
"Test reference"
}
}.ToFrozenDictionary();
""", result);
}

[Fact]
public void DumpFrozenDictionaryVb()
{
var frozenDictionary = new Dictionary<string, string>
{
{ "Steeve", "Test reference" }
}.ToFrozenDictionary();

var dumper = new VisualBasicDumper();

var result = dumper.Dump(frozenDictionary);

Assert.Equal("""
Dim lengthBucketsFrozenDictionaryOfString = New Dictionary(Of String, String) From {
{
"Steeve",
"Test reference"
}
}.ToFrozenDictionary()
""", result);
}
}
}

#endif
2 changes: 1 addition & 1 deletion test/UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net461</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;net461</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
Expand Down

0 comments on commit c74de34

Please sign in to comment.