Skip to content

Commit

Permalink
Merge pull request #70239 from CyrusNajmabadi/checksums2
Browse files Browse the repository at this point in the history
Fix checksum hierarchy
  • Loading branch information
CyrusNajmabadi authored Oct 5, 2023
2 parents 12f05db + 34b8f62 commit e7d4a39
Show file tree
Hide file tree
Showing 23 changed files with 891 additions and 874 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,8 @@ private void OnLspSolutionChanged(object? sender, WorkspaceChangeEventArgs e)
// If the document's attributes haven't changed, then use the document's URI for
// the call to EnqueueSemanticTokenRefreshNotification which will enable the
// tracking check before sending the WorkspaceSemanticTokensRefreshName message.
if (oldDocument?.State.Attributes is IChecksummedObject oldChecksumObject
&& newDocument.State.Attributes is IChecksummedObject newChecksumObject
&& oldChecksumObject.Checksum == newChecksumObject.Checksum)
{
if (oldDocument?.State.Attributes.Checksum == newDocument.State.Attributes.Checksum)
documentUri = newDocument.GetURI();
}
}
}

Expand Down
90 changes: 46 additions & 44 deletions src/VisualStudio/Core/Test.Next/Remote/SerializationValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;

Expand All @@ -32,7 +33,7 @@ public override async ValueTask<T> GetAssetAsync<T>(Checksum checksum, Cancellat
=> await _validator.GetValueAsync<T>(checksum).ConfigureAwait(false);
}

internal sealed class ChecksumObjectCollection<T> : IEnumerable<T> where T : ChecksumWithChildren
internal sealed class ChecksumObjectCollection<T> : IEnumerable<T>
{
public ImmutableArray<T> Children { get; }

Expand Down Expand Up @@ -107,10 +108,10 @@ public async Task<Solution> GetSolutionAsync(SolutionAssetStorage.Scope scope)
}

public ChecksumObjectCollection<ProjectStateChecksums> ToProjectObjects(ChecksumCollection collection)
=> new ChecksumObjectCollection<ProjectStateChecksums>(this, collection);
=> new(this, collection);

public ChecksumObjectCollection<DocumentStateChecksums> ToDocumentObjects(ChecksumCollection collection)
=> new ChecksumObjectCollection<DocumentStateChecksums>(this, collection);
=> new(this, collection);

internal async Task VerifyAssetAsync(SolutionStateChecksums solutionObject)
{
Expand Down Expand Up @@ -215,66 +216,67 @@ internal async Task VerifySolutionStateSerializationAsync(Solution solution, Che
SolutionStateEqual(solutionObjectFromSolution, solutionObjectFromSyncObject);
}

private static void AssertChecksumCollectionEqual(ChecksumCollection collection1, ChecksumCollection collection2)
{
Assert.Equal(collection1.Checksum, collection2.Checksum);
AssertEx.Equal(collection1.Children, collection2.Children);
}

internal void SolutionStateEqual(SolutionStateChecksums solutionObject1, SolutionStateChecksums solutionObject2)
{
ChecksumWithChildrenEqual(solutionObject1, solutionObject2);
Assert.Equal(solutionObject1.Checksum, solutionObject2.Checksum);
Assert.Equal(solutionObject1.Attributes, solutionObject2.Attributes);
AssertChecksumCollectionEqual(solutionObject1.Projects, solutionObject2.Projects);
AssertChecksumCollectionEqual(solutionObject1.AnalyzerReferences, solutionObject2.AnalyzerReferences);
Assert.Equal(solutionObject1.FrozenSourceGeneratedDocumentIdentity, solutionObject2.FrozenSourceGeneratedDocumentIdentity);
Assert.Equal(solutionObject1.FrozenSourceGeneratedDocumentText, solutionObject2.FrozenSourceGeneratedDocumentText);

ProjectStatesEqual(ToProjectObjects(solutionObject1.Projects), ToProjectObjects(solutionObject2.Projects));
}

internal void ProjectStateEqual(ProjectStateChecksums projectObjects1, ProjectStateChecksums projectObjects2)
private void ProjectStateEqual(ProjectStateChecksums projectObjects1, ProjectStateChecksums projectObjects2)
{
ChecksumWithChildrenEqual(projectObjects1, projectObjects2);
Assert.Equal(projectObjects1.Checksum, projectObjects2.Checksum);
Assert.Equal(projectObjects1.Info, projectObjects2.Info);
Assert.Equal(projectObjects1.CompilationOptions, projectObjects2.CompilationOptions);
Assert.Equal(projectObjects1.ParseOptions, projectObjects2.ParseOptions);
AssertChecksumCollectionEqual(projectObjects1.Documents, projectObjects2.Documents);
AssertChecksumCollectionEqual(projectObjects1.ProjectReferences, projectObjects2.ProjectReferences);
AssertChecksumCollectionEqual(projectObjects1.MetadataReferences, projectObjects2.MetadataReferences);
AssertChecksumCollectionEqual(projectObjects1.AnalyzerReferences, projectObjects2.AnalyzerReferences);
AssertChecksumCollectionEqual(projectObjects1.AdditionalDocuments, projectObjects2.AdditionalDocuments);
AssertChecksumCollectionEqual(projectObjects1.AnalyzerConfigDocuments, projectObjects2.AnalyzerConfigDocuments);

DocumentStatesEqual(ToDocumentObjects(projectObjects1.Documents), ToDocumentObjects(projectObjects2.Documents));
DocumentStatesEqual(ToDocumentObjects(projectObjects1.AdditionalDocuments), ToDocumentObjects(projectObjects2.AdditionalDocuments));
DocumentStatesEqual(ToDocumentObjects(projectObjects1.AnalyzerConfigDocuments), ToDocumentObjects(projectObjects2.AnalyzerConfigDocuments));
}

ChecksumWithChildrenEqual(ToDocumentObjects(projectObjects1.Documents), ToDocumentObjects(projectObjects2.Documents));
ChecksumWithChildrenEqual(ToDocumentObjects(projectObjects1.AdditionalDocuments), ToDocumentObjects(projectObjects2.AdditionalDocuments));
ChecksumWithChildrenEqual(ToDocumentObjects(projectObjects1.AnalyzerConfigDocuments), ToDocumentObjects(projectObjects2.AnalyzerConfigDocuments));
private static void DocumentStateEqual(DocumentStateChecksums documentObjects1, DocumentStateChecksums documentObjects2)
{
Assert.Equal(documentObjects1.Checksum, documentObjects2.Checksum);
Assert.Equal(documentObjects1.Info, documentObjects2.Info);
Assert.Equal(documentObjects1.Text, documentObjects2.Text);
}

internal void ProjectStatesEqual(ChecksumObjectCollection<ProjectStateChecksums> projectObjects1, ChecksumObjectCollection<ProjectStateChecksums> projectObjects2)
private void ProjectStatesEqual(ChecksumObjectCollection<ProjectStateChecksums> projectObjects1, ChecksumObjectCollection<ProjectStateChecksums> projectObjects2)
{
SynchronizationObjectEqual(projectObjects1, projectObjects2);

Assert.Equal(projectObjects1.Count, projectObjects2.Count);

for (var i = 0; i < projectObjects1.Count; i++)
{
ProjectStateEqual(projectObjects1[i], projectObjects2[i]);
}
}

internal static void ChecksumWithChildrenEqual<T>(ChecksumObjectCollection<T> checksums1, ChecksumObjectCollection<T> checksums2) where T : ChecksumWithChildren
{
SynchronizationObjectEqual(checksums1, checksums2);

Assert.Equal(checksums1.Count, checksums2.Count);

for (var i = 0; i < checksums1.Count; i++)
{
ChecksumWithChildrenEqual(checksums1[i], checksums2[i]);
}
}

internal static void ChecksumWithChildrenEqual(ChecksumWithChildren checksums1, ChecksumWithChildren checksums2)
private static void DocumentStatesEqual(ChecksumObjectCollection<DocumentStateChecksums> documentObjects1, ChecksumObjectCollection<DocumentStateChecksums> documentObjects2)
{
Assert.Equal(checksums1.Checksum, checksums2.Checksum);
Assert.Equal(checksums1.Children.Length, checksums2.Children.Length);
SynchronizationObjectEqual(documentObjects1, documentObjects2);

for (var i = 0; i < checksums1.Children.Length; i++)
{
var child1 = checksums1.Children[i];
var child2 = checksums2.Children[i];

Assert.Equal(child1.GetType(), child2.GetType());
Assert.Equal(documentObjects1.Count, documentObjects2.Count);

if (child1 is Checksum)
{
Assert.Equal((Checksum)child1, (Checksum)child2);
continue;
}

ChecksumWithChildrenEqual((ChecksumCollection)child1, (ChecksumCollection)child2);
}
for (var i = 0; i < documentObjects1.Count; i++)
DocumentStateEqual(documentObjects1[i], documentObjects2[i]);
}

internal async Task VerifySnapshotInServiceAsync(
Expand Down Expand Up @@ -331,7 +333,7 @@ internal async Task VerifySnapshotInServiceAsync(DocumentStateChecksums document
internal async Task VerifySynchronizationObjectInServiceAsync(SolutionAsset syncObject)
=> await VerifyChecksumInServiceAsync(syncObject.Checksum, syncObject.Kind).ConfigureAwait(false);

internal async Task VerifySynchronizationObjectInServiceAsync<T>(ChecksumObjectCollection<T> syncObject) where T : ChecksumWithChildren
internal async Task VerifySynchronizationObjectInServiceAsync<T>(ChecksumObjectCollection<T> syncObject)
=> await VerifyChecksumInServiceAsync(syncObject.Checksum, syncObject.Kind).ConfigureAwait(false);

internal async Task VerifyChecksumInServiceAsync(Checksum checksum, WellKnownSynchronizationKind kind)
Expand All @@ -342,10 +344,10 @@ internal async Task VerifyChecksumInServiceAsync(Checksum checksum, WellKnownSyn
ChecksumEqual(checksum, kind, otherObject.Checksum, otherObject.Kind);
}

internal static void SynchronizationObjectEqual<T>(ChecksumObjectCollection<T> checksumObject1, ChecksumObjectCollection<T> checksumObject2) where T : ChecksumWithChildren
internal static void SynchronizationObjectEqual<T>(ChecksumObjectCollection<T> checksumObject1, ChecksumObjectCollection<T> checksumObject2)
=> ChecksumEqual(checksumObject1.Checksum, checksumObject1.Kind, checksumObject2.Checksum, checksumObject2.Kind);

internal static void SynchronizationObjectEqual<T>(ChecksumObjectCollection<T> checksumObject1, SolutionAsset checksumObject2) where T : ChecksumWithChildren
internal static void SynchronizationObjectEqual<T>(ChecksumObjectCollection<T> checksumObject1, SolutionAsset checksumObject2)
=> ChecksumEqual(checksumObject1.Checksum, checksumObject1.Kind, checksumObject2.Checksum, checksumObject2.Kind);

internal static void SynchronizationObjectEqual(SolutionAsset checksumObject1, SolutionAsset checksumObject2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Remote.Testing;
using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests;
using Roslyn.Test.Utilities;
using Roslyn.Test.Utilities.TestGenerators;
using Roslyn.Utilities;
using Xunit;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
Expand All @@ -26,7 +25,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols
/// will still incur a heavy cost (for example, getting the <see cref="IAssemblySymbol"/> root symbol for a
/// particular project).
/// </summary>
internal partial class SymbolTreeInfo : IChecksummedObject
internal partial class SymbolTreeInfo
{
private static readonly StringComparer s_caseInsensitiveComparer =
CaseInsensitiveComparison.Comparer;
Expand Down Expand Up @@ -175,7 +174,7 @@ private async Task<ImmutableArray<ISymbol>> FuzzyFindAsync(
// up overwriting the field, but even if that happens, we are sure to see a fully written spell checker as
// the runtime guarantees that the initialize of the SpellChecker instnace completely written when we read
// our field.
_spellChecker ??= CreateSpellChecker(Checksum, _nodes);
_spellChecker ??= CreateSpellChecker(_nodes);
_spellChecker.FindSimilarWords(ref similarNames.AsRef(), name, substringsAreSimilar: false);

foreach (var similarName in similarNames)
Expand Down Expand Up @@ -297,8 +296,8 @@ private static int BinarySearch(ImmutableArray<Node> nodes, string name)

#region Construction

private static SpellChecker CreateSpellChecker(Checksum checksum, ImmutableArray<Node> sortedNodes)
=> new(checksum, sortedNodes.Select(n => n.Name));
private static SpellChecker CreateSpellChecker(ImmutableArray<Node> sortedNodes)
=> new(sortedNodes.Select(n => n.Name));

private static ImmutableArray<Node> SortNodes(ImmutableArray<BuilderNode> unsortedNodes)
{
Expand Down
31 changes: 8 additions & 23 deletions src/Workspaces/Core/Portable/Remote/ISerializerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,19 @@
// See the LICENSE file in the project root for more information.

using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Serialization
{
internal interface ISerializerService : IWorkspaceService
{
void Serialize(object value, ObjectWriter writer, SolutionReplicationContext context, CancellationToken cancellationToken);

void SerializeSourceText(SerializableSourceText text, ObjectWriter writer, SolutionReplicationContext context, CancellationToken cancellationToken);

void SerializeCompilationOptions(CompilationOptions options, ObjectWriter writer, CancellationToken cancellationToken);

void SerializeParseOptions(ParseOptions options, ObjectWriter writer);
namespace Microsoft.CodeAnalysis.Serialization;

void SerializeProjectReference(ProjectReference reference, ObjectWriter writer, CancellationToken cancellationToken);

void SerializeMetadataReference(MetadataReference reference, ObjectWriter writer, SolutionReplicationContext context, CancellationToken cancellationToken);

void SerializeAnalyzerReference(AnalyzerReference reference, ObjectWriter writer, CancellationToken cancellationToken);
internal interface ISerializerService : IWorkspaceService
{
void Serialize(object value, ObjectWriter writer, SolutionReplicationContext context, CancellationToken cancellationToken);

void SerializeChecksumWithChildren(ChecksumWithChildren checksums, ObjectWriter writer, CancellationToken cancellationToken);
void SerializeParseOptions(ParseOptions options, ObjectWriter writer);

T? Deserialize<T>(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken);
T? Deserialize<T>(WellKnownSynchronizationKind kind, ObjectReader reader, CancellationToken cancellationToken);

Checksum CreateChecksum(object value, CancellationToken cancellationToken);
Checksum CreateParseOptionsChecksum(ParseOptions value);
}
Checksum CreateChecksum(object value, CancellationToken cancellationToken);
Checksum CreateParseOptionsChecksum(ParseOptions value);
}
Loading

0 comments on commit e7d4a39

Please sign in to comment.