Skip to content

Commit

Permalink
Merge pull request #72996 from CyrusNajmabadi/syncCleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi authored Apr 12, 2024
2 parents 9f22861 + 6eb6457 commit 8a0cc11
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 187 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ namespace Roslyn.Utilities
{
internal static partial class EnumerableExtensions
{
public static int Count<T, TArg>(this IEnumerable<T> source, Func<T, TArg, bool> predicate, TArg arg)
{
var count = 0;
foreach (var v in source)
{
if (predicate(v, arg))
count++;
}

return count;
}

public static IEnumerable<T> Do<T>(this IEnumerable<T> source, Action<T> action)
{
if (source == null)
Expand Down
16 changes: 5 additions & 11 deletions src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,6 @@ internal async Task VerifySolutionStateSerializationAsync(Solution solution, Che
SolutionStateEqual(solutionObjectFromSolution, solutionObjectFromSyncObject);
}

private static void AssertChecksumCollectionEqual<TId>(
ChecksumsAndIds<TId> collection1, ChecksumsAndIds<TId> collection2)
{
AssertChecksumCollectionEqual(collection1.Checksums, collection2.Checksums);
AssertEx.Equal(collection1.Ids, collection2.Ids);
}

private static void AssertChecksumCollectionEqual(
ChecksumCollection collection1, ChecksumCollection collection2)
{
Expand All @@ -252,16 +245,17 @@ internal void SolutionCompilationStateEqual(SolutionCompilationStateChecksums so
if (solutionObject1.FrozenSourceGeneratedDocumentIdentities.HasValue)
AssertChecksumCollectionEqual(solutionObject1.FrozenSourceGeneratedDocumentIdentities.Value, solutionObject2.FrozenSourceGeneratedDocumentIdentities!.Value);

Assert.Equal(solutionObject1.FrozenSourceGeneratedDocumentTexts.HasValue, solutionObject2.FrozenSourceGeneratedDocumentTexts.HasValue);
if (solutionObject1.FrozenSourceGeneratedDocumentTexts.HasValue)
AssertChecksumCollectionEqual(solutionObject1.FrozenSourceGeneratedDocumentTexts.Value, solutionObject2.FrozenSourceGeneratedDocumentTexts!.Value);
Assert.Equal(solutionObject1.FrozenSourceGeneratedDocuments.HasValue, solutionObject2.FrozenSourceGeneratedDocuments.HasValue);
if (solutionObject1.FrozenSourceGeneratedDocuments.HasValue)
AssertDocumentChecksumCollectionEqual(solutionObject1.FrozenSourceGeneratedDocuments.Value, solutionObject2.FrozenSourceGeneratedDocuments!.Value);
}

internal void SolutionStateEqual(SolutionStateChecksums solutionObject1, SolutionStateChecksums solutionObject2)
{
Assert.Equal(solutionObject1.Checksum, solutionObject2.Checksum);
Assert.Equal(solutionObject1.Attributes, solutionObject2.Attributes);
AssertChecksumCollectionEqual(solutionObject1.Projects, solutionObject2.Projects);
AssertEx.Equals(solutionObject1.Projects.Ids, solutionObject2.Projects.Ids);
AssertChecksumCollectionEqual(solutionObject1.Projects.Checksums, solutionObject2.Projects.Checksums);
AssertChecksumCollectionEqual(solutionObject1.AnalyzerReferences, solutionObject2.AnalyzerReferences);

ProjectStatesEqual(ToProjectObjects(solutionObject1.Projects.Checksums), ToProjectObjects(solutionObject2.Projects.Checksums));
Expand Down
51 changes: 17 additions & 34 deletions src/Workspaces/Core/Portable/Workspace/Solution/ChecksumsAndIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Shared.Extensions;
Expand All @@ -11,36 +10,15 @@
namespace Microsoft.CodeAnalysis.Serialization;

/// <summary>
/// A paired list of IDs (either <see cref="ProjectId"/>s or <see cref="DocumentId"/>s), and the checksums for their
/// corresponding <see cref="Project"/>s or <see cref="Document"/>s).
/// A paired list of <see cref="ProjectId"/>s, and the checksums for their corresponding <see
/// cref="ProjectStateChecksums"/>'s <see cref="ProjectStateChecksums.Checksum"/>.
/// </summary>
internal readonly struct ChecksumsAndIds<TId>
internal readonly struct ProjectChecksumsAndIds
{
public readonly ChecksumCollection Checksums;
public readonly ImmutableArray<TId> Ids;
public readonly ImmutableArray<ProjectId> Ids;

private static readonly Func<ObjectReader, TId> s_readId;
private static readonly Action<ObjectWriter, TId> s_writeTo;

static ChecksumsAndIds()
{
if (typeof(TId) == typeof(ProjectId))
{
s_readId = reader => (TId)(object)ProjectId.ReadFrom(reader);
s_writeTo = (writer, id) => ((ProjectId)(object)id!).WriteTo(writer);
}
else if (typeof(TId) == typeof(DocumentId))
{
s_readId = reader => (TId)(object)DocumentId.ReadFrom(reader);
s_writeTo = (writer, id) => ((DocumentId)(object)id!).WriteTo(writer);
}
else
{
throw ExceptionUtilities.Unreachable();
}
}

public ChecksumsAndIds(ChecksumCollection checksums, ImmutableArray<TId> ids)
public ProjectChecksumsAndIds(ChecksumCollection checksums, ImmutableArray<ProjectId> ids)
{
Contract.ThrowIfTrue(ids.Length != checksums.Children.Length);

Expand All @@ -54,32 +32,37 @@ public ChecksumsAndIds(ChecksumCollection checksums, ImmutableArray<TId> ids)
public void WriteTo(ObjectWriter writer)
{
this.Checksums.WriteTo(writer);
writer.WriteArray(this.Ids, s_writeTo);
writer.WriteArray(this.Ids, static (writer, p) => p.WriteTo(writer));
}

public static ChecksumsAndIds<TId> ReadFrom(ObjectReader reader)
public static ProjectChecksumsAndIds ReadFrom(ObjectReader reader)
{
return new(
ChecksumCollection.ReadFrom(reader),
reader.ReadArray(s_readId));
reader.ReadArray(static reader => ProjectId.ReadFrom(reader)));
}

public Enumerator GetEnumerator()
=> new(this);

public struct Enumerator(ChecksumsAndIds<TId> checksumsAndIds)
public struct Enumerator(ProjectChecksumsAndIds checksumsAndIds)
{
private readonly ChecksumsAndIds<TId> _checksumsAndIds = checksumsAndIds;
private readonly ProjectChecksumsAndIds _checksumsAndIds = checksumsAndIds;
private int _index = -1;

public bool MoveNext()
=> ++_index < _checksumsAndIds.Length;

public (Checksum checksum, TId id) Current
public readonly (Checksum checksum, ProjectId id) Current
=> (_checksumsAndIds.Checksums.Children[_index], _checksumsAndIds.Ids[_index]);
}
}

/// <summary>
/// A paired list of <see cref="DocumentId"/>s, and the checksums for their corresponding <see
/// cref="DocumentStateChecksums"/>'s <see cref="DocumentStateChecksums.Info"/> and <see
/// cref="DocumentStateChecksums.Text"/> checksums.
/// </summary>
internal readonly struct DocumentChecksumsAndIds
{
public readonly Checksum Checksum;
Expand Down Expand Up @@ -133,7 +116,7 @@ public struct Enumerator(DocumentChecksumsAndIds checksumsAndIds)
public bool MoveNext()
=> ++_index < _checksumsAndIds.Length;

public (Checksum attributeChecksum, Checksum textChecksum, DocumentId id) Current
public readonly (Checksum attributeChecksum, Checksum textChecksum, DocumentId id) Current
=> (_checksumsAndIds.AttributeChecksums.Children[_index],
_checksumsAndIds.TextChecksums.Children[_index],
_checksumsAndIds.Ids[_index]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public Task<Checksum> GetDependentChecksumAsync(SolutionCompilationState compila
private async Task<Checksum> ComputeDependentChecksumAsync(SolutionCompilationState compilationState, CancellationToken cancellationToken)
=> Checksum.Create(
await UnderlyingTracker.GetDependentChecksumAsync(compilationState, cancellationToken).ConfigureAwait(false),
(await _replacementDocumentStates.GetChecksumsAndIdsAsync(cancellationToken).ConfigureAwait(false)).Checksum);
(await _replacementDocumentStates.GetDocumentChecksumsAndIdsAsync(cancellationToken).ConfigureAwait(false)).Checksum);

public MetadataReference? GetPartialMetadataReference(ProjectState fromProject, ProjectReference projectReference)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
Expand Down Expand Up @@ -125,7 +126,7 @@ public async Task<Checksum> GetChecksumAsync(ProjectId projectId, CancellationTo
}

ChecksumCollection? frozenSourceGeneratedDocumentIdentities = null;
ChecksumsAndIds<DocumentId>? frozenSourceGeneratedDocumentTexts = null;
DocumentChecksumsAndIds? frozenSourceGeneratedDocumentTexts = null;
ImmutableArray<DateTime> frozenSourceGeneratedDocumentGenerationDateTimes = default;

if (FrozenSourceGeneratedDocumentStates != null)
Expand All @@ -134,7 +135,7 @@ public async Task<Checksum> GetChecksumAsync(ProjectId projectId, CancellationTo
var identityChecksums = FrozenSourceGeneratedDocumentStates.SelectAsArray(
static (s, arg) => arg.serializer.CreateChecksum(s.Identity, cancellationToken: arg.cancellationToken), (serializer, cancellationToken));

frozenSourceGeneratedDocumentTexts = await FrozenSourceGeneratedDocumentStates.GetTextChecksumsAndIdsAsync(cancellationToken).ConfigureAwait(false);
frozenSourceGeneratedDocumentTexts = await FrozenSourceGeneratedDocumentStates.GetDocumentChecksumsAndIdsAsync(cancellationToken).ConfigureAwait(false);
frozenSourceGeneratedDocumentIdentities = new ChecksumCollection(identityChecksums);
frozenSourceGeneratedDocumentGenerationDateTimes = FrozenSourceGeneratedDocumentStates.SelectAsArray(d => d.GenerationDateTime);
}
Expand Down Expand Up @@ -163,8 +164,12 @@ static Checksum GetVersionMapChecksum(SolutionCompilationState @this)
// We want the projects in sorted order so we can generate the checksum for the
// source-generation-execution-map consistently.
var sortedProjectIds = SolutionState.GetOrCreateSortedProjectIds(@this.SolutionState.ProjectIds);
var supportedCount = sortedProjectIds.Count(
static (projectId, @this) => RemoteSupportedLanguages.IsSupported(@this.SolutionState.GetRequiredProjectState(projectId).Language),
@this);

using var _ = ArrayBuilder<Checksum>.GetInstance(out var checksums);
// For each project, we'll add one checksum for the project id and one for the version map.
using var _ = ArrayBuilder<Checksum>.GetInstance(2 * supportedCount, out var checksums);

foreach (var projectId in sortedProjectIds)
{
Expand Down
Loading

0 comments on commit 8a0cc11

Please sign in to comment.