Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR feedback on syncing. #72996

Merged
merged 24 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
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