Skip to content

Commit

Permalink
Switch to ImmutableArray for ChecksumWithCOllection
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Jul 29, 2022
1 parent 65435c5 commit 72c22c5
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,18 @@ public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IEnum
return builder.ToImmutableAndFree();
}

public static ImmutableArray<TResult> SelectAsArray<TSource, TResult>(this IReadOnlyCollection<TSource>? source, Func<TSource, TResult> selector)
{
if (source == null)
return ImmutableArray<TResult>.Empty;

var builder = ImmutableArray.CreateBuilder<TResult>(source.Count);
foreach (var item in source)
builder.Add(selector(item));

return builder.MoveToImmutable();
}

/// <summary>
/// Maps an immutable array through a function that returns ValueTask, returning the new ImmutableArray.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ internal static void ChecksumWithChildrenEqual<T>(ChecksumObjectCollection<T> ch
internal static void ChecksumWithChildrenEqual(ChecksumWithChildren checksums1, ChecksumWithChildren checksums2)
{
Assert.Equal(checksums1.Checksum, checksums2.Checksum);
Assert.Equal(checksums1.Children.Count, checksums2.Children.Count);
Assert.Equal(checksums1.Children.Length, checksums2.Children.Length);

for (var i = 0; i < checksums1.Children.Count; i++)
for (var i = 0; i < checksums1.Children.Length; i++)
{
var child1 = checksums1.Children[i];
var child2 = checksums2.Children[i];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Serialization
Expand All @@ -18,7 +19,7 @@ internal partial class SerializerService
private const byte ChecksumKind = 0;
private const byte ChecksumWithChildrenKind = 1;

private static readonly ImmutableDictionary<WellKnownSynchronizationKind, Func<object[], ChecksumWithChildren>> s_creatorMap = CreateCreatorMap();
private static readonly ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>> s_creatorMap = CreateCreatorMap();

public void SerializeChecksumWithChildren(ChecksumWithChildren checksums, ObjectWriter writer, CancellationToken cancellationToken)
{
Expand All @@ -28,7 +29,7 @@ public void SerializeChecksumWithChildren(ChecksumWithChildren checksums, Object
writer.WriteInt32((int)kind);
checksums.Checksum.WriteTo(writer);

writer.WriteInt32(checksums.Children.Count);
writer.WriteInt32(checksums.Children.Length);
foreach (var child in checksums.Children)
{
switch (child)
Expand All @@ -55,35 +56,34 @@ private ChecksumWithChildren DeserializeChecksumWithChildren(ObjectReader reader
var checksum = Checksum.ReadFrom(reader);

var childrenCount = reader.ReadInt32();
var children = new object[childrenCount];
var children = ImmutableArray.CreateBuilder<object>(childrenCount);

for (var i = 0; i < childrenCount; i++)
{
var childKind = reader.ReadByte();
if (childKind == ChecksumKind)
{
children[i] = Checksum.ReadFrom(reader);
continue;
children.Add(Checksum.ReadFrom(reader));
}

if (childKind == ChecksumWithChildrenKind)
else if (childKind == ChecksumWithChildrenKind)
{
children[i] = DeserializeChecksumWithChildren(reader, cancellationToken);
continue;
children.Add(DeserializeChecksumWithChildren(reader, cancellationToken));
}
else
{
throw ExceptionUtilities.UnexpectedValue(childKind);
}

throw ExceptionUtilities.UnexpectedValue(childKind);
}

var checksums = s_creatorMap[kind](children);
var checksums = s_creatorMap[kind](children.MoveToImmutable());
Contract.ThrowIfFalse(checksums.Checksum == checksum);

return checksums;
}

private static ImmutableDictionary<WellKnownSynchronizationKind, Func<object[], ChecksumWithChildren>> CreateCreatorMap()
private static ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>> CreateCreatorMap()
{
return ImmutableDictionary<WellKnownSynchronizationKind, Func<object[], ChecksumWithChildren>>.Empty
return ImmutableDictionary<WellKnownSynchronizationKind, Func<ImmutableArray<object>, ChecksumWithChildren>>.Empty
.Add(WellKnownSynchronizationKind.SolutionState, children => new SolutionStateChecksums(children))
.Add(WellKnownSynchronizationKind.ProjectState, children => new ProjectStateChecksums(children))
.Add(WellKnownSynchronizationKind.DocumentState, children => new DocumentStateChecksums(children))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ namespace Microsoft.CodeAnalysis.Serialization
/// </summary>
internal class ChecksumCollection : ChecksumWithChildren, IReadOnlyCollection<Checksum>
{
public ChecksumCollection(Checksum[] checksums) : this((object[])checksums)
public ChecksumCollection(ImmutableArray<Checksum> checksums) : this(checksums.CastArray<object>())
{
}

public ChecksumCollection(object[] checksums) : base(checksums)
public ChecksumCollection(ImmutableArray<object> checksums) : base(checksums)
{
}

public int Count => Children.Count;
public int Count => Children.Length;
public Checksum this[int index] => (Checksum)Children[index];

public IEnumerator<Checksum> GetEnumerator()
Expand Down Expand Up @@ -62,9 +62,9 @@ internal static void Find<T>(
Dictionary<Checksum, object> result,
CancellationToken cancellationToken)
{
Contract.ThrowIfFalse(values.Count == checksums.Children.Count);
Contract.ThrowIfFalse(values.Count == checksums.Children.Length);

for (var i = 0; i < checksums.Children.Count; i++)
for (var i = 0; i < checksums.Children.Length; i++)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace Microsoft.CodeAnalysis.Serialization
Expand All @@ -12,17 +13,17 @@ namespace Microsoft.CodeAnalysis.Serialization
/// </summary>
internal abstract class ChecksumWithChildren : IChecksummedObject
{
public ChecksumWithChildren(object[] children)
public ChecksumWithChildren(ImmutableArray<object> children)
{
Checksum = CreateChecksum(children);
Children = children;
}

public Checksum Checksum { get; }

public IReadOnlyList<object> Children { get; }
public ImmutableArray<object> Children { get; }

private static Checksum CreateChecksum(object[] children)
private static Checksum CreateChecksum(ImmutableArray<object> children)
{
// given children must be either Checksum or Checksums (collection of a checksum)
return Checksum.Create(children.Select(c => c as Checksum ?? ((ChecksumCollection)c).Checksum));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#nullable disable

using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -59,9 +60,9 @@ private async Task<ProjectStateChecksums> ComputeChecksumsAsync(CancellationToke
cancellationToken.ThrowIfCancellationRequested();
var parseOptionsChecksum = GetParseOptionsChecksum(serializer);

var projectReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(ProjectReferences, _ => new ChecksumCollection(ProjectReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));
var metadataReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(MetadataReferences, _ => new ChecksumCollection(MetadataReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));
var analyzerReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(AnalyzerReferences, _ => new ChecksumCollection(AnalyzerReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));
var projectReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(ProjectReferences, _ => new ChecksumCollection(ProjectReferences.SelectAsArray(r => serializer.CreateChecksum(r, cancellationToken))));
var metadataReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(MetadataReferences, _ => new ChecksumCollection(MetadataReferences.SelectAsArray(r => serializer.CreateChecksum(r, cancellationToken))));
var analyzerReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(AnalyzerReferences, _ => new ChecksumCollection(AnalyzerReferences.SelectAsArray(r => serializer.CreateChecksum(r, cancellationToken))));

var documentChecksums = await Task.WhenAll(documentChecksumsTasks).ConfigureAwait(false);
var additionalChecksums = await Task.WhenAll(additionalDocumentChecksumTasks).ConfigureAwait(false);
Expand All @@ -71,12 +72,12 @@ private async Task<ProjectStateChecksums> ComputeChecksumsAsync(CancellationToke
infoChecksum,
compilationOptionsChecksum,
parseOptionsChecksum,
documentChecksums: new ChecksumCollection(documentChecksums),
documentChecksums: new ChecksumCollection(ImmutableArray.Create(documentChecksums)),
projectReferenceChecksums,
metadataReferenceChecksums,
analyzerReferenceChecksums,
additionalDocumentChecksums: new ChecksumCollection(additionalChecksums),
analyzerConfigDocumentChecksumCollection: new ChecksumCollection(analyzerConfigDocumentChecksums));
additionalDocumentChecksums: new ChecksumCollection(ImmutableArray.Create(additionalChecksums)),
analyzerConfigDocumentChecksumCollection: new ChecksumCollection(ImmutableArray.Create(analyzerConfigDocumentChecksums)));
}
}
catch (Exception e) when (FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken, ErrorSeverity.Critical))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,12 @@ private async Task<SolutionStateChecksums> ComputeChecksumsAsync(
}

var analyzerReferenceChecksums = ChecksumCache.GetOrCreate<ChecksumCollection>(AnalyzerReferences,
_ => new ChecksumCollection(AnalyzerReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));
_ => new ChecksumCollection(AnalyzerReferences.SelectAsArray(r => serializer.CreateChecksum(r, cancellationToken))));

var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);
return new SolutionStateChecksums(
attributesChecksum,
new ChecksumCollection(projectChecksums.WhereNotNull().ToArray()),
new ChecksumCollection(projectChecksums.WhereNotNull().ToImmutableArray()),
analyzerReferenceChecksums,
frozenSourceGeneratedDocumentIdentityChecksum,
frozenSourceGeneratedDocumentTextChecksum);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
Expand All @@ -20,11 +21,11 @@ public SolutionStateChecksums(
ChecksumCollection analyzerReferenceChecksums,
Checksum frozenSourceGeneratedDocumentIdentity,
Checksum frozenSourceGeneratedDocumentText)
: this(new object[] { attributesChecksum, projectChecksums, analyzerReferenceChecksums, frozenSourceGeneratedDocumentIdentity, frozenSourceGeneratedDocumentText })
: this(ImmutableArray.Create<object>(attributesChecksum, projectChecksums, analyzerReferenceChecksums, frozenSourceGeneratedDocumentIdentity, frozenSourceGeneratedDocumentText))
{
}

public SolutionStateChecksums(object[] children) : base(children)
public SolutionStateChecksums(ImmutableArray<object> children) : base(children)
{
}

Expand Down Expand Up @@ -100,20 +101,20 @@ public ProjectStateChecksums(
ChecksumCollection analyzerReferenceChecksums,
ChecksumCollection additionalDocumentChecksums,
ChecksumCollection analyzerConfigDocumentChecksumCollection)
: this(
(object)infoChecksum,
: this(ImmutableArray.Create<object>(
infoChecksum,
compilationOptionsChecksum,
parseOptionsChecksum,
documentChecksums,
projectReferenceChecksums,
metadataReferenceChecksums,
analyzerReferenceChecksums,
additionalDocumentChecksums,
analyzerConfigDocumentChecksumCollection)
analyzerConfigDocumentChecksumCollection))
{
}

public ProjectStateChecksums(params object[] children) : base(children)
public ProjectStateChecksums(ImmutableArray<object> children) : base(children)
{
}

Expand Down Expand Up @@ -209,11 +210,11 @@ public async Task FindAsync(
internal class DocumentStateChecksums : ChecksumWithChildren
{
public DocumentStateChecksums(Checksum infoChecksum, Checksum textChecksum)
: this((object)infoChecksum, textChecksum)
: this(ImmutableArray.Create<object>(infoChecksum, textChecksum))
{
}

public DocumentStateChecksums(params object[] children) : base(children)
public DocumentStateChecksums(ImmutableArray<object> children) : base(children)
{
}

Expand Down

0 comments on commit 72c22c5

Please sign in to comment.