From 446629fa0fb5e261dc80b89c44edfc2d7f9dec94 Mon Sep 17 00:00:00 2001 From: Heejae Chang Date: Tue, 18 Oct 2016 02:44:00 -0700 Subject: [PATCH] removed serializedSolution/Project/DocumentInfo and rolled them into Solution/Project/DocumentInfo --- .../Core/Portable/Execution/Extensions.cs | 6 +- .../Core/Portable/Execution/Serializer.cs | 18 +- .../Portable/Execution/Serializer_Asset.cs | 136 +----- .../WellKnownSynchronizationKinds.cs | 6 +- .../Shared/Extensions/SolutionExtensions.cs | 13 +- .../Workspace/Solution/Checksum_Factory.cs | 12 + .../Portable/Workspace/Solution/DocumentId.cs | 21 +- .../Workspace/Solution/DocumentInfo.cs | 222 +++++++--- .../Portable/Workspace/Solution/ProjectId.cs | 17 +- .../Workspace/Solution/ProjectInfo.cs | 413 ++++++++++++------ .../Solution/ProjectState_Checksum.cs | 2 +- .../Workspace/Solution/SerializedInfos.cs | 78 ---- .../Portable/Workspace/Solution/SolutionId.cs | 17 +- .../Workspace/Solution/SolutionInfo.cs | 123 +++++- .../Workspace/Solution/SolutionState.cs | 75 ++-- .../Solution/SolutionState_Checksum.cs | 2 +- .../Workspace/Solution/StateChecksums.cs | 6 +- .../Solution/TextDocumentState_Checksum.cs | 2 +- .../Core/Portable/Workspaces.csproj | 1 - .../SnapshotSerializationTestBase.cs | 6 +- .../Execution/SnapshotSerializationTests.cs | 8 +- .../Remote/Core/Services/SolutionService.cs | 8 +- .../Diagnostics/DiagnosticResultSerializer.cs | 6 +- 23 files changed, 673 insertions(+), 525 deletions(-) delete mode 100644 src/Workspaces/Core/Portable/Workspace/Solution/SerializedInfos.cs diff --git a/src/Workspaces/Core/Portable/Execution/Extensions.cs b/src/Workspaces/Core/Portable/Execution/Extensions.cs index 70ec8b0e754..33ff847caba 100644 --- a/src/Workspaces/Core/Portable/Execution/Extensions.cs +++ b/src/Workspaces/Core/Portable/Execution/Extensions.cs @@ -62,17 +62,17 @@ public static string GetWellKnownSynchronizationKind(this object value) return WellKnownSynchronizationKinds.AnalyzerReferences; } - if (value is SerializedSolutionInfo) + if (value is SolutionInfo.SolutionAttributes) { return WellKnownSynchronizationKinds.SolutionInfo; } - if (value is SerializedProjectInfo) + if (value is ProjectInfo.ProjectAttributes) { return WellKnownSynchronizationKinds.ProjectInfo; } - if (value is SerializedDocumentInfo) + if (value is DocumentInfo.DocumentAttributes) { return WellKnownSynchronizationKinds.DocumentInfo; } diff --git a/src/Workspaces/Core/Portable/Execution/Serializer.cs b/src/Workspaces/Core/Portable/Execution/Serializer.cs index d80478bb574..8f82d7e3395 100644 --- a/src/Workspaces/Core/Portable/Execution/Serializer.cs +++ b/src/Workspaces/Core/Portable/Execution/Serializer.cs @@ -6,7 +6,6 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Execution; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -52,9 +51,6 @@ public Checksum CreateChecksum(object value, CancellationToken cancellationToken case WellKnownSynchronizationKinds.Null: return Checksum.Null; - case WellKnownSynchronizationKinds.SolutionInfo: - case WellKnownSynchronizationKinds.ProjectInfo: - case WellKnownSynchronizationKinds.DocumentInfo: case WellKnownSynchronizationKinds.CompilationOptions: case WellKnownSynchronizationKinds.ParseOptions: case WellKnownSynchronizationKinds.ProjectReference: @@ -98,15 +94,9 @@ public void Serialize(object value, ObjectWriter writer, CancellationToken cance return; case WellKnownSynchronizationKinds.SolutionInfo: - SerializeSerializedSolutionInfo((SerializedSolutionInfo)value, writer, cancellationToken); - return; - case WellKnownSynchronizationKinds.ProjectInfo: - SerializeSerializedProjectInfo((SerializedProjectInfo)value, writer, cancellationToken); - return; - case WellKnownSynchronizationKinds.DocumentInfo: - SerializeSerializedDocumentInfo((SerializedDocumentInfo)value, writer, cancellationToken); + ((IObjectWritable)value).WriteTo(writer); return; case WellKnownSynchronizationKinds.CompilationOptions: @@ -164,11 +154,11 @@ public T Deserialize(string kind, ObjectReader reader, CancellationToken canc return (T)(object)DeserializeChecksumWithChildren(reader, cancellationToken); case WellKnownSynchronizationKinds.SolutionInfo: - return (T)(object)DeserializeSerializedSolutionInfo(reader, cancellationToken); + return (T)(object)SolutionInfo.SolutionAttributes.ReadFrom(reader); case WellKnownSynchronizationKinds.ProjectInfo: - return (T)(object)DeserializeSerializedProjectInfo(reader, cancellationToken); + return (T)(object)ProjectInfo.ProjectAttributes.ReadFrom(reader); case WellKnownSynchronizationKinds.DocumentInfo: - return (T)(object)DeserializeSerializedDocumentInfo(reader, cancellationToken); + return (T)(object)DocumentInfo.DocumentAttributes.ReadFrom(reader); case WellKnownSynchronizationKinds.CompilationOptions: return (T)(object)DeserializeCompilationOptions(reader, cancellationToken); case WellKnownSynchronizationKinds.ParseOptions: diff --git a/src/Workspaces/Core/Portable/Execution/Serializer_Asset.cs b/src/Workspaces/Core/Portable/Execution/Serializer_Asset.cs index 3f5659d36cd..db3c4f53d1c 100644 --- a/src/Workspaces/Core/Portable/Execution/Serializer_Asset.cs +++ b/src/Workspaces/Core/Portable/Execution/Serializer_Asset.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Execution; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; @@ -19,91 +20,6 @@ namespace Microsoft.CodeAnalysis.Serialization /// internal partial class Serializer { - public void SerializeSerializedSolutionInfo(SerializedSolutionInfo info, ObjectWriter writer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - SerializeSolutionId(info.Id, writer, cancellationToken); - - // TODO: figure out a way to send version info over as well. - // right now, version get updated automatically, so 2 can't be exactly match - // info.Version.WriteTo(writer); - writer.WriteString(info.FilePath); - } - - private SerializedSolutionInfo DeserializeSerializedSolutionInfo(ObjectReader reader, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var solutionId = DeserializeSolutionId(reader, cancellationToken); - // var version = VersionStamp.ReadFrom(reader); - var filePath = reader.ReadString(); - - return new SerializedSolutionInfo(solutionId, VersionStamp.Create(), filePath); - } - - public void SerializeSerializedProjectInfo(SerializedProjectInfo info, ObjectWriter writer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - SerializeProjectId(info.Id, writer, cancellationToken); - - // TODO: figure out a way to send version info over as well - // info.Version.WriteTo(writer); - - writer.WriteString(info.Name); - writer.WriteString(info.AssemblyName); - writer.WriteString(info.Language); - writer.WriteString(info.FilePath); - writer.WriteString(info.OutputFilePath); - writer.WriteBoolean(info.IsSubmission); - } - - private SerializedProjectInfo DeserializeSerializedProjectInfo(ObjectReader reader, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var projectId = DeserializeProjectId(reader, cancellationToken); - - // var version = VersionStamp.ReadFrom(reader); - var name = reader.ReadString(); - var assemblyName = reader.ReadString(); - var language = reader.ReadString(); - var filePath = reader.ReadString(); - var outputFilePath = reader.ReadString(); - var isSubmission = reader.ReadBoolean(); - - return new SerializedProjectInfo(projectId, VersionStamp.Create(), name, assemblyName, language, filePath, outputFilePath, isSubmission); - } - - public void SerializeSerializedDocumentInfo(SerializedDocumentInfo info, ObjectWriter writer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - SerializeDocumentId(info.Id, writer, cancellationToken); - - writer.WriteString(info.Name); - writer.WriteValue(info.Folders.ToArray()); - writer.WriteInt32((int)info.SourceCodeKind); - writer.WriteString(info.FilePath); - writer.WriteBoolean(info.IsGenerated); - } - - private SerializedDocumentInfo DeserializeSerializedDocumentInfo(ObjectReader reader, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var documentId = DeserializeDocumentId(reader, cancellationToken); - - var name = reader.ReadString(); - var folders = reader.ReadArray(); - var sourceCodeKind = reader.ReadInt32(); - var filePath = reader.ReadString(); - var isGenerated = reader.ReadBoolean(); - - return new SerializedDocumentInfo(documentId, name, folders, (SourceCodeKind)sourceCodeKind, filePath, isGenerated); - } - public void SerializeSourceText(ITemporaryStorageWithName storage, SourceText text, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -205,7 +121,7 @@ public void SerializeProjectReference(ProjectReference reference, ObjectWriter w { cancellationToken.ThrowIfCancellationRequested(); - SerializeProjectId(reference.ProjectId, writer, cancellationToken); + reference.ProjectId.WriteTo(writer); writer.WriteValue(reference.Aliases.ToArray()); writer.WriteBoolean(reference.EmbedInteropTypes); } @@ -214,7 +130,7 @@ private ProjectReference DeserializeProjectReference(ObjectReader reader, Cancel { cancellationToken.ThrowIfCancellationRequested(); - var projectId = DeserializeProjectId(reader, cancellationToken); + var projectId = ProjectId.ReadFrom(reader); var aliases = reader.ReadArray(); var embedInteropTypes = reader.ReadBoolean(); @@ -244,51 +160,5 @@ private AnalyzerReference DeserializeAnalyzerReference(ObjectReader reader, Canc cancellationToken.ThrowIfCancellationRequested(); return _hostSerializationService.ReadAnalyzerReferenceFrom(reader, cancellationToken); } - - public void SerializeSolutionId(SolutionId solutionId, ObjectWriter writer, CancellationToken cancellationToken) - { - writer.WriteValue(solutionId.Id.ToByteArray()); - writer.WriteString(solutionId.DebugName); - } - - private SolutionId DeserializeSolutionId(ObjectReader reader, CancellationToken cancellationToken) - { - var guid = new Guid(reader.ReadArray()); - var debugName = reader.ReadString(); - - return SolutionId.CreateFromSerialized(guid, debugName); - } - - public static void SerializeProjectId(ProjectId projectId, ObjectWriter writer, CancellationToken cancellationToken) - { - writer.WriteValue(projectId.Id.ToByteArray()); - writer.WriteString(projectId.DebugName); - } - - public static ProjectId DeserializeProjectId(ObjectReader reader, CancellationToken cancellationToken) - { - var guid = new Guid(reader.ReadArray()); - var debugName = reader.ReadString(); - - return ProjectId.CreateFromSerialized(guid, debugName); - } - - public static void SerializeDocumentId(DocumentId documentId, ObjectWriter writer, CancellationToken cancellationToken) - { - SerializeProjectId(documentId.ProjectId, writer, cancellationToken); - - writer.WriteValue(documentId.Id.ToByteArray()); - writer.WriteString(documentId.DebugName); - } - - public static DocumentId DeserializeDocumentId(ObjectReader reader, CancellationToken cancellationToken) - { - var projectId = DeserializeProjectId(reader, cancellationToken); - - var guid = new Guid(reader.ReadArray()); - var debugName = reader.ReadString(); - - return DocumentId.CreateFromSerialized(projectId, guid, debugName); - } } } diff --git a/src/Workspaces/Core/Portable/Execution/WellKnownSynchronizationKinds.cs b/src/Workspaces/Core/Portable/Execution/WellKnownSynchronizationKinds.cs index 2aca8876d56..20d406cf59d 100644 --- a/src/Workspaces/Core/Portable/Execution/WellKnownSynchronizationKinds.cs +++ b/src/Workspaces/Core/Portable/Execution/WellKnownSynchronizationKinds.cs @@ -18,9 +18,9 @@ internal static class WellKnownSynchronizationKinds public const string MetadataReferences = nameof(MetadataReferenceChecksumCollection); public const string AnalyzerReferences = nameof(AnalyzerReferenceChecksumCollection); - public const string SolutionInfo = nameof(SerializedSolutionInfo); - public const string ProjectInfo = nameof(SerializedProjectInfo); - public const string DocumentInfo = nameof(SerializedDocumentInfo); + public const string SolutionInfo = nameof(CodeAnalysis.SolutionInfo.SolutionAttributes); + public const string ProjectInfo = nameof(CodeAnalysis.ProjectInfo.ProjectAttributes); + public const string DocumentInfo = nameof(CodeAnalysis.DocumentInfo.DocumentAttributes); public const string CompilationOptions = nameof(CompilationOptions); public const string ParseOptions = nameof(ParseOptions); diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SolutionExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SolutionExtensions.cs index ffc0d7ae084..c4bacbd549c 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/SolutionExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SolutionExtensions.cs @@ -1,19 +1,14 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Roslyn.Utilities; + namespace Microsoft.CodeAnalysis.Shared.Extensions { internal static class SolutionExtensions { - public static SourceCodeKind GetSourceCodeKind(this TextDocumentState state) - { - // these can just be abstract property - return (state as DocumentState)?.SourceCodeKind ?? SourceCodeKind.Regular; - } - - public static bool IsGenerated(this TextDocumentState state) + public static void WriteTo(this IObjectWritable @object, ObjectWriter writer) { - // these can just be abstract property - return (state as DocumentState)?.IsGenerated ?? false; + @object.WriteTo(writer); } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs index 6ea4937f3bc..cb61967ec25 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/Checksum_Factory.cs @@ -63,5 +63,17 @@ public static Checksum Create(T value, string kind, Serializer serializer) return Create(stream); } } + + public static Checksum Create(IObjectWritable @object, string kind) + { + using (var stream = SerializableBytes.CreateWritableStream()) + using (var objectWriter = new ObjectWriter(stream)) + { + objectWriter.WriteString(kind); + @object.WriteTo(objectWriter); + + return Create(stream); + } + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentId.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentId.cs index d24f96456c2..64a5d020a18 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentId.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentId.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -12,7 +13,7 @@ namespace Microsoft.CodeAnalysis /// workspace. /// [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] - public sealed class DocumentId : IEquatable + public sealed class DocumentId : IEquatable, IObjectWritable { public ProjectId ProjectId { get; } public Guid Id { get; } @@ -96,5 +97,23 @@ public override int GetHashCode() { return !(left == right); } + + void IObjectWritable.WriteTo(ObjectWriter writer) + { + ProjectId.WriteTo(writer); + + writer.WriteValue(Id.ToByteArray()); + writer.WriteString(DebugName); + } + + internal static DocumentId ReadFrom(ObjectReader reader) + { + var projectId = ProjectId.ReadFrom(reader); + + var guid = new Guid((byte[])reader.ReadValue()); + var debugName = reader.ReadString(); + + return CreateFromSerialized(projectId, guid, debugName); + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs index b146056edee..02d3ad29e01 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentInfo.cs @@ -1,8 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -13,70 +15,50 @@ namespace Microsoft.CodeAnalysis [DebuggerDisplay("{GetDebuggerDisplay() , nq}")] public sealed class DocumentInfo { + internal DocumentAttributes Attributes { get; } + /// /// The Id of the document. /// - public DocumentId Id { get; } + public DocumentId Id => Attributes.Id; /// /// The name of the document. /// - public string Name { get; } + public string Name => Attributes.Name; /// /// The names of the logical nested folders the document is contained in. /// - public IReadOnlyList Folders { get; } + public IReadOnlyList Folders => Attributes.Folders; /// /// The kind of the source code. /// - public SourceCodeKind SourceCodeKind { get; } + public SourceCodeKind SourceCodeKind => Attributes.SourceCodeKind; /// /// The file path of the document. /// - public string FilePath { get; } + public string FilePath => Attributes.FilePath; /// - /// A loader that can retrieve the document text. + /// True if the document is a side effect of the build. /// - public TextLoader TextLoader { get; } + public bool IsGenerated => Attributes.IsGenerated; /// - /// True if the document is a side effect of the build. + /// A loader that can retrieve the document text. /// - public bool IsGenerated { get; } + public TextLoader TextLoader { get; } /// /// Create a new instance of a . /// - private DocumentInfo( - DocumentId id, - string name, - IEnumerable folders, - SourceCodeKind sourceCodeKind, - TextLoader loader, - string filePath, - bool isGenerated) + private DocumentInfo(DocumentAttributes attributes, TextLoader loader) { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - this.Id = id; - this.Name = name; - this.Folders = folders.ToImmutableReadOnlyListOrEmpty(); - this.SourceCodeKind = sourceCodeKind; - this.TextLoader = loader; - this.FilePath = filePath; - this.IsGenerated = isGenerated; + Attributes = attributes; + TextLoader = loader; } public static DocumentInfo Create( @@ -88,70 +70,186 @@ public sealed class DocumentInfo string filePath = null, bool isGenerated = false) { - return new DocumentInfo(id, name, folders, sourceCodeKind, loader, filePath, isGenerated); + return new DocumentInfo(new DocumentAttributes(id, name, folders, sourceCodeKind, filePath, isGenerated), loader); } private DocumentInfo With( - DocumentId id = null, - string name = null, - IEnumerable folders = null, - Optional sourceCodeKind = default(Optional), - Optional loader = default(Optional), - Optional filePath = default(Optional)) + DocumentAttributes attributes = null, + Optional loader = default(Optional)) { - var newId = id ?? this.Id; - var newName = name ?? this.Name; - var newFolders = folders ?? this.Folders; - var newSourceCodeKind = sourceCodeKind.HasValue ? sourceCodeKind.Value : this.SourceCodeKind; - var newLoader = loader.HasValue ? loader.Value : this.TextLoader; - var newFilePath = filePath.HasValue ? filePath.Value : this.FilePath; - - if (newId == this.Id && - newName == this.Name && - newFolders == this.Folders && - newSourceCodeKind == this.SourceCodeKind && - newLoader == this.TextLoader && - newFilePath == this.FilePath) + var newAttributes = attributes ?? Attributes; + var newLoader = loader.HasValue ? loader.Value : TextLoader; + + if (newAttributes == Attributes && newLoader == TextLoader) { return this; } - return new DocumentInfo(newId, newName, newFolders, newSourceCodeKind, newLoader, newFilePath, this.IsGenerated); + return new DocumentInfo(newAttributes, newLoader); } public DocumentInfo WithId(DocumentId id) { - return this.With(id: id); + return With(attributes: Attributes.With(id: id)); } public DocumentInfo WithName(string name) { - return this.With(name: name); + return this.With(attributes: Attributes.With(name: name)); } public DocumentInfo WithFolders(IEnumerable folders) { - return this.With(folders: folders.ToImmutableReadOnlyListOrEmpty()); + return this.With(attributes: Attributes.With(folders: folders.ToImmutableReadOnlyListOrEmpty())); } public DocumentInfo WithSourceCodeKind(SourceCodeKind kind) { - return this.With(sourceCodeKind: kind); + return this.With(attributes: Attributes.With(sourceCodeKind: kind)); } public DocumentInfo WithTextLoader(TextLoader loader) { - return this.With(loader: loader); + return With(loader: loader); } public DocumentInfo WithFilePath(string filePath) { - return this.With(filePath: filePath); + return this.With(attributes: Attributes.With(filePath: filePath)); } private string GetDebuggerDisplay() { return (FilePath == null) ? (nameof(Name) + " = " + Name) : (nameof(FilePath) + " = " + FilePath); } + + /// + /// type that contains information regarding this document itself but + /// no tree information such as document info + /// + internal class DocumentAttributes : IChecksummedObject, IObjectWritable + { + /// + /// The Id of the document. + /// + public DocumentId Id { get; } + + /// + /// The name of the document. + /// + public string Name { get; } + + /// + /// The names of the logical nested folders the document is contained in. + /// + public IReadOnlyList Folders { get; } + + /// + /// The kind of the source code. + /// + public SourceCodeKind SourceCodeKind { get; } + + /// + /// The file path of the document. + /// + public string FilePath { get; } + + /// + /// True if the document is a side effect of the build. + /// + public bool IsGenerated { get; } + + public DocumentAttributes( + DocumentId id, + string name, + IEnumerable folders, + SourceCodeKind sourceCodeKind, + string filePath, + bool isGenerated) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + Id = id; + Name = name; + Folders = folders.ToImmutableReadOnlyListOrEmpty(); + SourceCodeKind = sourceCodeKind; + FilePath = filePath; + IsGenerated = isGenerated; + } + + public DocumentAttributes With( + DocumentId id = null, + string name = null, + IEnumerable folders = null, + Optional sourceCodeKind = default(Optional), + Optional filePath = default(Optional), + Optional isGenerated = default(Optional)) + { + var newId = id ?? Id; + var newName = name ?? Name; + var newFolders = folders ?? Folders; + var newSourceCodeKind = sourceCodeKind.HasValue ? sourceCodeKind.Value : SourceCodeKind; + var newFilePath = filePath.HasValue ? filePath.Value : FilePath; + var newIsGenerated = isGenerated.HasValue ? isGenerated.Value : IsGenerated; + + if (newId == Id && + newName == Name && + newFolders == Folders && + newSourceCodeKind == SourceCodeKind && + newFilePath == FilePath && + newIsGenerated == IsGenerated) + { + return this; + } + + return new DocumentAttributes(newId, newName, newFolders, newSourceCodeKind, newFilePath, newIsGenerated); + } + + public void WriteTo(ObjectWriter writer) + { + Id.WriteTo(writer); + + writer.WriteString(Name); + writer.WriteValue(Folders.ToArray()); + writer.WriteInt32((int)SourceCodeKind); + writer.WriteString(FilePath); + writer.WriteBoolean(IsGenerated); + } + + public static DocumentAttributes ReadFrom(ObjectReader reader) + { + var documentId = DocumentId.ReadFrom(reader); + + var name = reader.ReadString(); + var folders = (string[])reader.ReadValue(); + var sourceCodeKind = reader.ReadInt32(); + var filePath = reader.ReadString(); + var isGenerated = reader.ReadBoolean(); + + return new DocumentAttributes(documentId, name, folders, (SourceCodeKind)sourceCodeKind, filePath, isGenerated); + } + + private Checksum _lazyChecksum; + Checksum IChecksummedObject.Checksum + { + get + { + if (_lazyChecksum == null) + { + _lazyChecksum = Checksum.Create(this, nameof(DocumentAttributes)); + } + + return _lazyChecksum; + } + } + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs index 860c40f8d64..fd1eec299a0 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectId.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -10,7 +11,7 @@ namespace Microsoft.CodeAnalysis /// An identifier that can be used to refer to the same across versions. /// [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] - public sealed class ProjectId : IEquatable + public sealed class ProjectId : IEquatable, IObjectWritable { private readonly string _debugName; @@ -82,5 +83,19 @@ public override int GetHashCode() { return this.Id.GetHashCode(); } + + void IObjectWritable.WriteTo(ObjectWriter writer) + { + writer.WriteValue(Id.ToByteArray()); + writer.WriteString(DebugName); + } + + internal static ProjectId ReadFrom(ObjectReader reader) + { + var guid = new Guid((byte[])reader.ReadValue()); + var debugName = reader.ReadString(); + + return CreateFromSerialized(guid, debugName); + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs index 3b172f816a3..bfbd149b332 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectInfo.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -14,40 +15,54 @@ namespace Microsoft.CodeAnalysis [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] public sealed class ProjectInfo { + internal ProjectAttributes Attributes { get; } + /// /// The unique Id of the project. /// - public ProjectId Id { get; } + public ProjectId Id => Attributes.Id; /// /// The version of the project. /// - public VersionStamp Version { get; } + public VersionStamp Version => Attributes.Version; /// /// The name of the project. This may differ from the project's filename. /// - public string Name { get; } + public string Name => Attributes.Name; /// /// The name of the assembly that this project will create, without file extension. /// , - public string AssemblyName { get; } + public string AssemblyName => Attributes.AssemblyName; /// /// The language of the project. /// - public string Language { get; } + public string Language => Attributes.Language; /// /// The path to the project file or null if there is no project file. /// - public string FilePath { get; } + public string FilePath => Attributes.FilePath; /// /// The path to the output file (module or assembly). /// - public string OutputFilePath { get; } + public string OutputFilePath => Attributes.OutputFilePath; + + /// + /// True if this is a submission project for interactive sessions. + /// + public bool IsSubmission => Attributes.IsSubmission; + + /// + /// True if project information is complete. In some workspace hosts, it is possible + /// a project only has partial information. In such cases, a project might not have all + /// information on its files or references. + /// + internal bool HasAllInformation => Attributes.HasAllInformation; /// /// The initial compilation options for the project, or null if the default options should be used. @@ -84,31 +99,13 @@ public sealed class ProjectInfo /// public IReadOnlyList AdditionalDocuments { get; } - /// - /// True if this is a submission project for interactive sessions. - /// - public bool IsSubmission { get; } - /// /// Type of the host object. /// public Type HostObjectType { get; } - /// - /// True if project information is complete. In some workspace hosts, it is possible - /// a project only has partial information. In such cases, a project might not have all - /// information on its files or references. - /// - internal bool HasAllInformation { get; } - private ProjectInfo( - ProjectId id, - VersionStamp version, - string name, - string assemblyName, - string language, - string filePath, - string outputFilePath, + ProjectAttributes attributes, CompilationOptions compilationOptions, ParseOptions parseOptions, IEnumerable documents, @@ -116,47 +113,17 @@ public sealed class ProjectInfo IEnumerable metadataReferences, IEnumerable analyzerReferences, IEnumerable additionalDocuments, - bool isSubmission, - Type hostObjectType, - bool hasAllInformation) + Type hostObjectType) { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - if (assemblyName == null) - { - throw new ArgumentNullException(nameof(assemblyName)); - } - - if (language == null) - { - throw new ArgumentNullException(nameof(language)); - } - - this.Id = id; - this.Version = version; - this.Name = name; - this.AssemblyName = assemblyName; - this.Language = language; - this.FilePath = filePath; - this.OutputFilePath = outputFilePath; - this.CompilationOptions = compilationOptions; - this.ParseOptions = parseOptions; - this.Documents = documents.ToImmutableReadOnlyListOrEmpty(); - this.ProjectReferences = projectReferences.ToImmutableReadOnlyListOrEmpty(); - this.MetadataReferences = metadataReferences.ToImmutableReadOnlyListOrEmpty(); - this.AnalyzerReferences = analyzerReferences.ToImmutableReadOnlyListOrEmpty(); - this.AdditionalDocuments = additionalDocuments.ToImmutableReadOnlyListOrEmpty(); - this.IsSubmission = isSubmission; - this.HostObjectType = hostObjectType; - this.HasAllInformation = hasAllInformation; + Attributes = attributes; + CompilationOptions = compilationOptions; + ParseOptions = parseOptions; + Documents = documents.ToImmutableReadOnlyListOrEmpty(); + ProjectReferences = projectReferences.ToImmutableReadOnlyListOrEmpty(); + MetadataReferences = metadataReferences.ToImmutableReadOnlyListOrEmpty(); + AnalyzerReferences = analyzerReferences.ToImmutableReadOnlyListOrEmpty(); + AdditionalDocuments = additionalDocuments.ToImmutableReadOnlyListOrEmpty(); + HostObjectType = hostObjectType; } /// @@ -182,13 +149,16 @@ public sealed class ProjectInfo bool hasAllInformation) { return new ProjectInfo( - id, - version, - name, - assemblyName, - language, - filePath, - outputFilePath, + new ProjectAttributes( + id, + version, + name, + assemblyName, + language, + filePath, + outputFilePath, + isSubmission, + hasAllInformation), compilationOptions, parseOptions, documents, @@ -196,9 +166,7 @@ public sealed class ProjectInfo metadataReferences, analyzerReferences, additionalDocuments, - isSubmission, - hostObjectType, - hasAllInformation); + hostObjectType); } /// @@ -230,13 +198,7 @@ public sealed class ProjectInfo } private ProjectInfo With( - ProjectId id = null, - VersionStamp? version = default(VersionStamp?), - string name = null, - string assemblyName = null, - string language = null, - Optional filePath = default(Optional), - Optional outputPath = default(Optional), + ProjectAttributes attributes = null, CompilationOptions compilationOptions = null, ParseOptions parseOptions = null, IEnumerable documents = null, @@ -244,57 +206,33 @@ public sealed class ProjectInfo IEnumerable metadataReferences = null, IEnumerable analyzerReferences = null, IEnumerable additionalDocuments = null, - Optional isSubmission = default(Optional), - Optional hostObjectType = default(Optional), - Optional hasAllInformation = default(Optional)) + Optional hostObjectType = default(Optional)) { - var newId = id ?? this.Id; - var newVersion = version.HasValue ? version.Value : this.Version; - var newName = name ?? this.Name; - var newAssemblyName = assemblyName ?? this.AssemblyName; - var newLanguage = language ?? this.Language; - var newFilepath = filePath.HasValue ? filePath.Value : this.FilePath; - var newOutputPath = outputPath.HasValue ? outputPath.Value : this.OutputFilePath; - var newCompilationOptions = compilationOptions ?? this.CompilationOptions; - var newParseOptions = parseOptions ?? this.ParseOptions; - var newDocuments = documents ?? this.Documents; - var newProjectReferences = projectReferences ?? this.ProjectReferences; - var newMetadataReferences = metadataReferences ?? this.MetadataReferences; - var newAnalyzerReferences = analyzerReferences ?? this.AnalyzerReferences; - var newAdditionalDocuments = additionalDocuments ?? this.AdditionalDocuments; - var newIsSubmission = isSubmission.HasValue ? isSubmission.Value : this.IsSubmission; - var newHostObjectType = hostObjectType.HasValue ? hostObjectType.Value : this.HostObjectType; - var newHasAllInformation = hasAllInformation.HasValue ? hasAllInformation.Value : this.HasAllInformation; - - if (newId == this.Id && - newVersion == this.Version && - newName == this.Name && - newAssemblyName == this.AssemblyName && - newLanguage == this.Language && - newFilepath == this.FilePath && - newOutputPath == this.OutputFilePath && - newCompilationOptions == this.CompilationOptions && - newParseOptions == this.ParseOptions && - newDocuments == this.Documents && - newProjectReferences == this.ProjectReferences && - newMetadataReferences == this.MetadataReferences && - newAnalyzerReferences == this.AnalyzerReferences && - newAdditionalDocuments == this.AdditionalDocuments && - newIsSubmission == this.IsSubmission && - newHostObjectType == this.HostObjectType && - newHasAllInformation == this.HasAllInformation) + var newAttributes = attributes ?? Attributes; + var newCompilationOptions = compilationOptions ?? CompilationOptions; + var newParseOptions = parseOptions ?? ParseOptions; + var newDocuments = documents ?? Documents; + var newProjectReferences = projectReferences ?? ProjectReferences; + var newMetadataReferences = metadataReferences ?? MetadataReferences; + var newAnalyzerReferences = analyzerReferences ?? AnalyzerReferences; + var newAdditionalDocuments = additionalDocuments ?? AdditionalDocuments; + var newHostObjectType = hostObjectType.HasValue ? hostObjectType.Value : HostObjectType; + + if (newAttributes == Attributes && + newCompilationOptions == CompilationOptions && + newParseOptions == ParseOptions && + newDocuments == Documents && + newProjectReferences == ProjectReferences && + newMetadataReferences == MetadataReferences && + newAnalyzerReferences == AnalyzerReferences && + newAdditionalDocuments == AdditionalDocuments && + newHostObjectType == HostObjectType) { return this; } return new ProjectInfo( - newId, - newVersion, - newName, - newAssemblyName, - newLanguage, - newFilepath, - newOutputPath, + newAttributes, newCompilationOptions, newParseOptions, newDocuments, @@ -302,79 +240,266 @@ public sealed class ProjectInfo newMetadataReferences, newAnalyzerReferences, newAdditionalDocuments, - newIsSubmission, - newHostObjectType, - newHasAllInformation); + newHostObjectType); } public ProjectInfo WithDocuments(IEnumerable documents) { - return this.With(documents: documents.ToImmutableReadOnlyListOrEmpty()); + return With(documents: documents.ToImmutableReadOnlyListOrEmpty()); } public ProjectInfo WithAdditionalDocuments(IEnumerable additionalDocuments) { - return this.With(additionalDocuments: additionalDocuments.ToImmutableReadOnlyListOrEmpty()); + return With(additionalDocuments: additionalDocuments.ToImmutableReadOnlyListOrEmpty()); } public ProjectInfo WithVersion(VersionStamp version) { - return this.With(version: version); + return With(attributes: Attributes.With(version: version)); } public ProjectInfo WithName(string name) { - return this.With(name: name); + return With(attributes: Attributes.With(name: name)); } public ProjectInfo WithFilePath(string filePath) { - return this.With(filePath: filePath); + return With(attributes: Attributes.With(filePath: filePath)); } public ProjectInfo WithAssemblyName(string assemblyName) { - return this.With(assemblyName: assemblyName); + return With(attributes: Attributes.With(assemblyName: assemblyName)); } public ProjectInfo WithOutputFilePath(string outputFilePath) { - return this.With(outputPath: outputFilePath); + return With(attributes: Attributes.With(outputPath: outputFilePath)); } public ProjectInfo WithCompilationOptions(CompilationOptions compilationOptions) { - return this.With(compilationOptions: compilationOptions); + return With(compilationOptions: compilationOptions); } public ProjectInfo WithParseOptions(ParseOptions parseOptions) { - return this.With(parseOptions: parseOptions); + return With(parseOptions: parseOptions); } public ProjectInfo WithProjectReferences(IEnumerable projectReferences) { - return this.With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty()); + return With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty()); } public ProjectInfo WithMetadataReferences(IEnumerable metadataReferences) { - return this.With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty()); + return With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty()); } public ProjectInfo WithAnalyzerReferences(IEnumerable analyzerReferences) { - return this.With(analyzerReferences: analyzerReferences.ToImmutableReadOnlyListOrEmpty()); + return With(analyzerReferences: analyzerReferences.ToImmutableReadOnlyListOrEmpty()); } internal ProjectInfo WithHasAllInformation(bool hasAllInformation) { - return this.With(hasAllInformation: hasAllInformation); + return With(attributes: Attributes.With(hasAllInformation: hasAllInformation)); } internal string GetDebuggerDisplay() { return nameof(ProjectInfo) + " " + Name + (!string.IsNullOrWhiteSpace(FilePath) ? " " + FilePath : ""); } + + /// + /// type that contains information regarding this project itself but + /// no tree information such as document info + /// + internal class ProjectAttributes : IChecksummedObject, IObjectWritable + { + /// + /// The unique Id of the project. + /// + public ProjectId Id { get; } + + /// + /// The version of the project. + /// + public VersionStamp Version { get; } + + /// + /// The name of the project. This may differ from the project's filename. + /// + public string Name { get; } + + /// + /// The name of the assembly that this project will create, without file extension. + /// , + public string AssemblyName { get; } + + /// + /// The language of the project. + /// + public string Language { get; } + + /// + /// The path to the project file or null if there is no project file. + /// + public string FilePath { get; } + + /// + /// The path to the output file (module or assembly). + /// + public string OutputFilePath { get; } + + /// + /// True if this is a submission project for interactive sessions. + /// + public bool IsSubmission { get; } + + /// + /// True if project information is complete. In some workspace hosts, it is possible + /// a project only has partial information. In such cases, a project might not have all + /// information on its files or references. + /// + public bool HasAllInformation { get; } + + public ProjectAttributes( + ProjectId id, + VersionStamp version, + string name, + string assemblyName, + string language, + string filePath, + string outputFilePath, + bool isSubmission, + bool hasAllInformation) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + if (language == null) + { + throw new ArgumentNullException(nameof(language)); + } + + if (assemblyName == null) + { + throw new ArgumentNullException(nameof(assemblyName)); + } + + Id = id; + Name = name; + Language = language; + AssemblyName = assemblyName; + + Version = version; + FilePath = filePath; + OutputFilePath = outputFilePath; + IsSubmission = isSubmission; + HasAllInformation = hasAllInformation; + } + + public ProjectAttributes With( + VersionStamp? version = default(VersionStamp?), + string name = null, + string assemblyName = null, + string language = null, + Optional filePath = default(Optional), + Optional outputPath = default(Optional), + Optional isSubmission = default(Optional), + Optional hasAllInformation = default(Optional)) + { + var newVersion = version.HasValue ? version.Value : Version; + var newName = name ?? Name; + var newAssemblyName = assemblyName ?? AssemblyName; + var newLanguage = language ?? Language; + var newFilepath = filePath.HasValue ? filePath.Value : FilePath; + var newOutputPath = outputPath.HasValue ? outputPath.Value : OutputFilePath; + var newIsSubmission = isSubmission.HasValue ? isSubmission.Value : IsSubmission; + var newHasAllInformation = hasAllInformation.HasValue ? hasAllInformation.Value : HasAllInformation; + + if (newVersion == Version && + newName == Name && + newAssemblyName == AssemblyName && + newLanguage == Language && + newFilepath == FilePath && + newOutputPath == OutputFilePath && + newIsSubmission == IsSubmission && + newHasAllInformation == HasAllInformation) + { + return this; + } + + return new ProjectAttributes( + Id, + newVersion, + newName, + newAssemblyName, + newLanguage, + newFilepath, + newOutputPath, + newIsSubmission, + newHasAllInformation); + } + + public void WriteTo(ObjectWriter writer) + { + Id.WriteTo(writer); + + // TODO: figure out a way to send version info over as well + // info.Version.WriteTo(writer); + + writer.WriteString(Name); + writer.WriteString(AssemblyName); + writer.WriteString(Language); + writer.WriteString(FilePath); + writer.WriteString(OutputFilePath); + writer.WriteBoolean(IsSubmission); + writer.WriteBoolean(HasAllInformation); + + // TODO: once CompilationOptions, ParseOptions, ProjectReference, MetadataReference, AnalyzerReference supports + // serialization, we should include those here as well. + } + + public static ProjectAttributes ReadFrom(ObjectReader reader) + { + var projectId = ProjectId.ReadFrom(reader); + + // var version = VersionStamp.ReadFrom(reader); + var name = reader.ReadString(); + var assemblyName = reader.ReadString(); + var language = reader.ReadString(); + var filePath = reader.ReadString(); + var outputFilePath = reader.ReadString(); + var isSubmission = reader.ReadBoolean(); + var hasAllInformation = reader.ReadBoolean(); + + return new ProjectAttributes(projectId, VersionStamp.Create(), name, assemblyName, language, filePath, outputFilePath, isSubmission, hasAllInformation); + } + + private Checksum _lazyChecksum; + Checksum IChecksummedObject.Checksum + { + get + { + if (_lazyChecksum == null) + { + _lazyChecksum = Checksum.Create(this, nameof(ProjectAttributes)); + } + + return _lazyChecksum; + } + } + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState_Checksum.cs b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState_Checksum.cs index 319591d0828..c32d9a77488 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState_Checksum.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/ProjectState_Checksum.cs @@ -31,7 +31,7 @@ private async Task ComputeChecksumsAsync(CancellationToke var serializer = new Serializer(_solutionServices.Workspace.Services); - var infoChecksum = serializer.CreateChecksum(new SerializedProjectInfo(Id, Version, Name, AssemblyName, Language, FilePath, OutputFilePath, IsSubmission), cancellationToken); + var infoChecksum = serializer.CreateChecksum(ProjectInfo.Attributes, cancellationToken); var compilationOptionsChecksum = SupportsCompilation ? serializer.CreateChecksum(CompilationOptions, cancellationToken) : Checksum.Null; var parseOptionsChecksum = SupportsCompilation ? serializer.CreateChecksum(ParseOptions, cancellationToken) : Checksum.Null; diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SerializedInfos.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SerializedInfos.cs deleted file mode 100644 index dd66b76c174..00000000000 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SerializedInfos.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Collections.Generic; - -namespace Microsoft.CodeAnalysis.Serialization -{ - /// - /// types to hold information in solution info/project info or document info that remote host will have as well. - /// - /// TODO: right now, any kind of version is not synced to remote host since it requires some changes in workspace. - /// but we should sync versions to remote host as well when we make workspace available in remote host. - /// for now, even if remote host uses workspace for things like resolving p2p references, only public service - /// clients can use are APIs compiler layer expose. - /// - internal sealed class SerializedSolutionInfo - { - public readonly SolutionId Id; - public readonly VersionStamp Version; - public readonly string FilePath; - - public SerializedSolutionInfo(SolutionId id, VersionStamp version, string filePath) - { - Id = id; - Version = version; - FilePath = filePath; - } - } - - internal sealed class SerializedProjectInfo - { - // REVIEW: do we need this? - // HostObjectType, HasAllInformation, Top Level Version, Latest Document Version - - public readonly ProjectId Id; - public readonly VersionStamp Version; - public readonly string Name; - public readonly string AssemblyName; - public readonly string Language; - public readonly string FilePath; - public readonly string OutputFilePath; - public readonly bool IsSubmission; - - public SerializedProjectInfo(ProjectId id, VersionStamp version, string name, string assemblyName, string language, string filePath, string outputFilePath, bool isSubmission) - { - Id = id; - Version = version; - Name = name; - AssemblyName = assemblyName; - Language = language; - FilePath = filePath; - OutputFilePath = outputFilePath; - IsSubmission = isSubmission; - } - } - - internal sealed class SerializedDocumentInfo - { - // REVIEW: do we need this? - // Tree Version, Text Version - - public readonly DocumentId Id; - public readonly string Name; - public readonly IReadOnlyList Folders; - public readonly SourceCodeKind SourceCodeKind; - public readonly string FilePath; - public readonly bool IsGenerated; - - public SerializedDocumentInfo(DocumentId id, string name, IReadOnlyList folders, SourceCodeKind sourceCodeKind, string filePath, bool isGenerated) - { - Id = id; - Name = name; - Folders = folders; - SourceCodeKind = sourceCodeKind; - FilePath = filePath; - IsGenerated = isGenerated; - } - } -} diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionId.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionId.cs index f91f738194c..486f3074ba0 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionId.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionId.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis { @@ -10,7 +11,7 @@ namespace Microsoft.CodeAnalysis /// An identifier that can be used to refer to the same Solution across versions. /// [DebuggerDisplay("{GetDebuggerDisplay(),nq}")] - public sealed class SolutionId : IEquatable + public sealed class SolutionId : IEquatable, IObjectWritable { /// /// The unique id of the solution. @@ -79,5 +80,19 @@ public override int GetHashCode() { return this.Id.GetHashCode(); } + + void IObjectWritable.WriteTo(ObjectWriter writer) + { + writer.WriteValue(Id.ToByteArray()); + writer.WriteString(DebugName); + } + + internal static SolutionId ReadFrom(ObjectReader reader) + { + var guid = new Guid((byte[])reader.ReadValue()); + var debugName = reader.ReadString(); + + return CreateFromSerialized(guid, debugName); + } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionInfo.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionInfo.cs index 5430d1da658..2c1e45df4e0 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionInfo.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; +using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis @@ -10,36 +12,32 @@ namespace Microsoft.CodeAnalysis /// public sealed class SolutionInfo { + internal SolutionAttributes Attributes { get; } + /// /// The unique Id of the solution. /// - public SolutionId Id { get; } + public SolutionId Id => Attributes.Id; /// /// The version of the solution. /// - public VersionStamp Version { get; } + public VersionStamp Version => Attributes.Version; /// /// The path to the solution file, or null if there is no solution file. /// - public string FilePath { get; } + public string FilePath => Attributes.FilePath; /// /// A list of projects initially associated with the solution. /// public IReadOnlyList Projects { get; } - private SolutionInfo( - SolutionId id, - VersionStamp version, - string filePath, - IEnumerable projects) + private SolutionInfo(SolutionAttributes attributes, IEnumerable projects) { - this.Id = id; - this.Version = version; - this.FilePath = filePath; - this.Projects = projects.ToImmutableReadOnlyListOrEmpty(); + Attributes = attributes; + Projects = projects.ToImmutableReadOnlyListOrEmpty(); } /// @@ -51,7 +49,106 @@ public sealed class SolutionInfo string filePath = null, IEnumerable projects = null) { - return new SolutionInfo(id, version, filePath, projects); + return new SolutionInfo(new SolutionAttributes(id, version, filePath), projects); + } + + private SolutionInfo With( + SolutionAttributes attributes = null, + IEnumerable projects = null) + { + var newAttributes = attributes ?? Attributes; + var newProjects = projects ?? Projects; + + if (newAttributes == Attributes && + newProjects == Projects) + { + return this; + } + + return new SolutionInfo(newAttributes, newProjects); + } + + internal SolutionInfo WithVersion(VersionStamp version) + { + return With(attributes: new SolutionAttributes(Attributes.Id, version, Attributes.FilePath)); + } + + internal SolutionInfo WithFilePath(string filePath) + { + return With(attributes: new SolutionAttributes(Attributes.Id, Attributes.Version, filePath)); + } + + internal SolutionInfo WithProjects(IEnumerable projects) + { + return With(projects: projects); + } + + /// + /// type that contains information regarding this solution itself but + /// no tree information such as project info + /// + internal class SolutionAttributes : IChecksummedObject, IObjectWritable + { + /// + /// The unique Id of the solution. + /// + public SolutionId Id { get; } + + /// + /// The version of the solution. + /// + public VersionStamp Version { get; } + + /// + /// The path to the solution file, or null if there is no solution file. + /// + public string FilePath { get; } + + public SolutionAttributes(SolutionId id, VersionStamp version, string filePath) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + Id = id; + Version = version; + FilePath = filePath; + } + + public void WriteTo(ObjectWriter writer) + { + Id.WriteTo(writer); + + // TODO: figure out a way to send version info over as well. + // right now, version get updated automatically, so 2 can't be exactly match + // info.Version.WriteTo(writer); + + writer.WriteString(FilePath); + } + + public static SolutionAttributes ReadFrom(ObjectReader reader) + { + var solutionId = SolutionId.ReadFrom(reader); + // var version = VersionStamp.ReadFrom(reader); + var filePath = reader.ReadString(); + + return new SolutionAttributes(solutionId, VersionStamp.Create(), filePath); + } + + private Checksum _lazyChecksum; + Checksum IChecksummedObject.Checksum + { + get + { + if (_lazyChecksum == null) + { + _lazyChecksum = Checksum.Create(this, nameof(SolutionAttributes)); + } + + return _lazyChecksum; + } + } } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs index f2672fd7eea..23dc1b259b1 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState.cs @@ -30,13 +30,11 @@ internal partial class SolutionState // the version of the workspace this solution is from private readonly int _workspaceVersion; + private readonly SolutionInfo _solutionInfo; private readonly SolutionServices _solutionServices; - private readonly SolutionId _id; - private readonly string _filePath; private readonly IReadOnlyList _projectIds; private readonly ImmutableDictionary _projectIdToProjectStateMap; private readonly ImmutableDictionary> _linkedFilesMap; - private readonly VersionStamp _version; private readonly Lazy _lazyLatestProjectVersion; private readonly ProjectDependencyGraph _dependencyGraph; @@ -50,32 +48,26 @@ internal partial class SolutionState BranchId branchId, int workspaceVersion, SolutionServices solutionServices, - SolutionId id, - string filePath, + SolutionInfo solutionInfo, IEnumerable projectIds, ImmutableDictionary idToProjectStateMap, ImmutableDictionary projectIdToTrackerMap, ImmutableDictionary> linkedFilesMap, ProjectDependencyGraph dependencyGraph, - VersionStamp version, - Lazy lazyLatestProjectVersion, - ValueSource lazyChecksums) + Lazy lazyLatestProjectVersion) { _branchId = branchId; _workspaceVersion = workspaceVersion; - _id = id; - _filePath = filePath; _solutionServices = solutionServices; + _solutionInfo = solutionInfo; _projectIds = projectIds.ToImmutableReadOnlyListOrEmpty(); _projectIdToProjectStateMap = idToProjectStateMap; _projectIdToTrackerMap = projectIdToTrackerMap; _linkedFilesMap = linkedFilesMap; _dependencyGraph = dependencyGraph; - _version = version; _lazyLatestProjectVersion = lazyLatestProjectVersion; - // for now, let it re-calculate if anything changed. - // TODO: optimize this so that we only re-calcuate checksums that are actually changed + // when solution state is changed, we re-calcuate its checksum _lazyChecksums = new AsyncLazy(ComputeChecksumsAsync, cacheResult: true); CheckInvariants(); @@ -88,16 +80,13 @@ internal partial class SolutionState workspace.PrimaryBranchId, workspaceVersion: 0, solutionServices: new SolutionServices(workspace), - id: info.Id, - filePath: info.FilePath, - version: info.Version, + solutionInfo: info, projectIds: null, idToProjectStateMap: ImmutableDictionary.Empty, projectIdToTrackerMap: ImmutableDictionary.Empty, linkedFilesMap: ImmutableDictionary.Create>(StringComparer.OrdinalIgnoreCase), dependencyGraph: ProjectDependencyGraph.Empty, - lazyLatestProjectVersion: null, - lazyChecksums: null) + lazyLatestProjectVersion: null) { // this is for the very first solution state ever created _lazyLatestProjectVersion = new Lazy(() => ComputeLatestProjectVersion()); @@ -127,6 +116,8 @@ private VersionStamp ComputeLatestProjectVersion() return latestVersion; } + public SolutionInfo SolutionInfo => _solutionInfo; + public ImmutableDictionary ProjectStates => _projectIdToProjectStateMap; public int WorkspaceVersion => _workspaceVersion; @@ -154,17 +145,17 @@ private VersionStamp ComputeLatestProjectVersion() /// /// The Id of the solution. Multiple solution instances may share the same Id. /// - public SolutionId Id => _id; + public SolutionId Id => _solutionInfo.Id; /// /// The path to the solution file or null if there is no solution file. /// - public string FilePath => _filePath; + public string FilePath => _solutionInfo.FilePath; /// /// The solution version. This equates to the solution file's version. /// - public VersionStamp Version => _version; + public VersionStamp Version => _solutionInfo.Version; /// /// A list of all the ids for all the projects contained by the solution. @@ -181,53 +172,48 @@ private void CheckInvariants() } private SolutionState Branch( + SolutionInfo solutionInfo = null, IEnumerable projectIds = null, ImmutableDictionary idToProjectStateMap = null, ImmutableDictionary projectIdToTrackerMap = null, ImmutableDictionary> linkedFilesMap = null, ProjectDependencyGraph dependencyGraph = null, - VersionStamp? version = default(VersionStamp?), - Lazy lazyLatestProjectVersion = null, - ValueSource lazyChecksums = null) + Lazy lazyLatestProjectVersion = null) { var branchId = GetBranchId(); + solutionInfo = solutionInfo ?? _solutionInfo; projectIds = projectIds ?? _projectIds; idToProjectStateMap = idToProjectStateMap ?? _projectIdToProjectStateMap; projectIdToTrackerMap = projectIdToTrackerMap ?? _projectIdToTrackerMap; linkedFilesMap = linkedFilesMap ?? _linkedFilesMap; dependencyGraph = dependencyGraph ?? _dependencyGraph; - version = version.HasValue ? version.Value : _version; lazyLatestProjectVersion = lazyLatestProjectVersion ?? _lazyLatestProjectVersion; - lazyChecksums = lazyChecksums ?? _lazyChecksums; if (branchId == _branchId && + solutionInfo == _solutionInfo && projectIds == _projectIds && idToProjectStateMap == _projectIdToProjectStateMap && projectIdToTrackerMap == _projectIdToTrackerMap && linkedFilesMap == _linkedFilesMap && dependencyGraph == _dependencyGraph && - version == _version && - lazyLatestProjectVersion == _lazyLatestProjectVersion && - lazyChecksums == _lazyChecksums) + lazyLatestProjectVersion == _lazyLatestProjectVersion) { return this; } + return new SolutionState( branchId, _workspaceVersion, _solutionServices, - _id, - _filePath, + solutionInfo, projectIds, idToProjectStateMap, projectIdToTrackerMap, linkedFilesMap, dependencyGraph, - version.Value, - lazyLatestProjectVersion, - lazyChecksums); + lazyLatestProjectVersion); } private SolutionState CreatePrimarySolution( @@ -246,16 +232,13 @@ private void CheckInvariants() branchId, workspaceVersion, services, - _id, - _filePath, + _solutionInfo, _projectIds, _projectIdToProjectStateMap, _projectIdToTrackerMap, _linkedFilesMap, _dependencyGraph, - _version, - _lazyLatestProjectVersion, - _lazyChecksums); + _lazyLatestProjectVersion); } private BranchId GetBranchId() @@ -428,6 +411,10 @@ private CompilationTracker GetCompilationTracker(ProjectId projectId) private SolutionState AddProject(ProjectId projectId, ProjectState projectState) { + // changed project list so, increment version. + var newSolutionInfo = _solutionInfo.WithVersion(this.Version.GetNewerVersion()) + .WithProjects(_solutionInfo.Projects.Concat(projectState.ProjectInfo)); + var newProjectIds = _projectIds.ToImmutableArray().Add(projectId); var newStateMap = _projectIdToProjectStateMap.Add(projectId, projectState); var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap); @@ -435,12 +422,12 @@ private SolutionState AddProject(ProjectId projectId, ProjectState projectState) var newLinkedFilesMap = CreateLinkedFilesMapWithAddedProject(newStateMap[projectId]); return this.Branch( + solutionInfo: newSolutionInfo, projectIds: newProjectIds, idToProjectStateMap: newStateMap, projectIdToTrackerMap: newTrackerMap, linkedFilesMap: newLinkedFilesMap, dependencyGraph: newDependencyGraph, - version: this.Version.GetNewerVersion(), // changed project list so, increment version. lazyLatestProjectVersion: new Lazy(() => projectState.Version)); // this is the newest! } @@ -520,6 +507,10 @@ public SolutionState RemoveProject(ProjectId projectId) CheckContainsProject(projectId); + // changed project list so, increment version. + var newSolutionInfo = _solutionInfo.WithVersion(this.Version.GetNewerVersion()) + .WithProjects(_solutionInfo.Projects.Where(s => s.Id != projectId)); + var newProjectIds = _projectIds.ToImmutableArray().Remove(projectId); var newStateMap = _projectIdToProjectStateMap.Remove(projectId); var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap); @@ -527,12 +518,12 @@ public SolutionState RemoveProject(ProjectId projectId) var newLinkedFilesMap = CreateLinkedFilesMapWithRemovedProject(_projectIdToProjectStateMap[projectId]); return this.Branch( + solutionInfo: newSolutionInfo, projectIds: newProjectIds, idToProjectStateMap: newStateMap, projectIdToTrackerMap: newTrackerMap.Remove(projectId), linkedFilesMap: newLinkedFilesMap, - dependencyGraph: newDependencyGraph, - version: this.Version.GetNewerVersion()); // changed project list, so increment version + dependencyGraph: newDependencyGraph); } private ImmutableDictionary> CreateLinkedFilesMapWithRemovedProject(ProjectState projectState) diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs index f618f7fa7d8..99434591f6b 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/SolutionState_Checksum.cs @@ -29,7 +29,7 @@ private async Task ComputeChecksumsAsync(CancellationTok var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id].GetChecksumAsync(cancellationToken)); var serializer = new Serializer(_solutionServices.Workspace.Services); - var infoChecksum = serializer.CreateChecksum(new SerializedSolutionInfo(Id, Version, FilePath), cancellationToken); + var infoChecksum = serializer.CreateChecksum(SolutionInfo.Attributes, cancellationToken); var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false); return new SolutionStateChecksums(infoChecksum, new ProjectChecksumCollection(projectChecksums)); diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs b/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs index a2c1c87749e..295639f7bca 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs @@ -47,7 +47,7 @@ public SolutionStateChecksums With(Checksum infoChecksum = null, ProjectChecksum if (searchingChecksumsLeft.Remove(Info)) { - result[Info] = new SerializedSolutionInfo(state.Id, state.Version, state.FilePath); + result[Info] = state.SolutionInfo.Attributes; } if (searchingChecksumsLeft.Remove(Projects.Checksum)) @@ -152,7 +152,7 @@ public ProjectStateChecksums(params object[] children) : base(nameof(ProjectStat if (searchingChecksumsLeft.Remove(Info)) { - result[Info] = new SerializedProjectInfo(state.Id, state.Version, state.Name, state.AssemblyName, state.Language, state.FilePath, state.OutputFilePath, state.IsSubmission); + result[Info] = state.ProjectInfo.Attributes; } if (searchingChecksumsLeft.Remove(CompilationOptions)) @@ -286,7 +286,7 @@ public DocumentStateChecksums With(Checksum infoChecksum = null, Checksum textCh if (searchingChecksumsLeft.Remove(Info)) { - result[Info] = new SerializedDocumentInfo(state.Id, state.Name, state.Folders, state.GetSourceCodeKind(), state.FilePath, state.IsGenerated()); + result[Info] = state.Info.Attributes; } if (searchingChecksumsLeft.Remove(Text)) diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState_Checksum.cs b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState_Checksum.cs index 7a3555de207..adc63229e82 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState_Checksum.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/TextDocumentState_Checksum.cs @@ -29,7 +29,7 @@ private async Task ComputeChecksumsAsync(CancellationTok var serializer = new Serializer(solutionServices.Workspace.Services); - var infoChecksum = serializer.CreateChecksum(new SerializedDocumentInfo(Id, Name, Folders, this.GetSourceCodeKind(), FilePath, this.IsGenerated()), cancellationToken); + var infoChecksum = serializer.CreateChecksum(Info.Attributes, cancellationToken); var textChecksum = serializer.CreateChecksum(await textTask.ConfigureAwait(false), cancellationToken); return new DocumentStateChecksums(infoChecksum, textChecksum); diff --git a/src/Workspaces/Core/Portable/Workspaces.csproj b/src/Workspaces/Core/Portable/Workspaces.csproj index 5d9b254a910..83d633a12da 100644 --- a/src/Workspaces/Core/Portable/Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Workspaces.csproj @@ -988,7 +988,6 @@ - diff --git a/src/Workspaces/CoreTest/Execution/SnapshotSerializationTestBase.cs b/src/Workspaces/CoreTest/Execution/SnapshotSerializationTestBase.cs index f167cb5d288..f25a91c03af 100644 --- a/src/Workspaces/CoreTest/Execution/SnapshotSerializationTestBase.cs +++ b/src/Workspaces/CoreTest/Execution/SnapshotSerializationTestBase.cs @@ -38,7 +38,7 @@ internal static Solution CreateFullSolution(HostServices hostServices = null) internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, SolutionStateChecksums solutionObject) { - await VerifyAssetSerializationAsync( + await VerifyAssetSerializationAsync( service, solutionObject.Info, WellKnownSynchronizationKinds.SolutionInfo, (v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); @@ -51,7 +51,7 @@ internal static async Task VerifyAssetAsync(ISolutionSynchronizationService serv internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, ProjectStateChecksums projectObject) { - var info = await VerifyAssetSerializationAsync( + var info = await VerifyAssetSerializationAsync( service, projectObject.Info, WellKnownSynchronizationKinds.ProjectInfo, (v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); @@ -99,7 +99,7 @@ internal static async Task VerifyAssetAsync(ISolutionSynchronizationService serv internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, DocumentStateChecksums documentObject) { - var info = await VerifyAssetSerializationAsync( + var info = await VerifyAssetSerializationAsync( service, documentObject.Info, WellKnownSynchronizationKinds.DocumentInfo, (v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); diff --git a/src/Workspaces/CoreTest/Execution/SnapshotSerializationTests.cs b/src/Workspaces/CoreTest/Execution/SnapshotSerializationTests.cs index 9c530a95452..032d89a3458 100644 --- a/src/Workspaces/CoreTest/Execution/SnapshotSerializationTests.cs +++ b/src/Workspaces/CoreTest/Execution/SnapshotSerializationTests.cs @@ -471,12 +471,12 @@ private async Task GetSolutionAsync(ISolutionSynchronizationService se var workspace = new AdhocWorkspace(); var solutionObject = await service.GetValueAsync(syncScope.SolutionChecksum); - var solutionInfo = await service.GetValueAsync(solutionObject.Info).ConfigureAwait(false); + var solutionInfo = await service.GetValueAsync(solutionObject.Info).ConfigureAwait(false); var projects = new List(); foreach (var projectObject in solutionObject.Projects.ToProjectObjects(service)) { - var projectInfo = await service.GetValueAsync(projectObject.Info).ConfigureAwait(false); + var projectInfo = await service.GetValueAsync(projectObject.Info).ConfigureAwait(false); if (!workspace.Services.IsSupported(projectInfo.Language)) { continue; @@ -485,7 +485,7 @@ private async Task GetSolutionAsync(ISolutionSynchronizationService se var documents = new List(); foreach (var documentObject in projectObject.Documents.ToDocumentObjects(service)) { - var documentInfo = await service.GetValueAsync(documentObject.Info).ConfigureAwait(false); + var documentInfo = await service.GetValueAsync(documentObject.Info).ConfigureAwait(false); var text = await service.GetValueAsync(documentObject.Text).ConfigureAwait(false); // TODO: do we need version? @@ -524,7 +524,7 @@ private async Task GetSolutionAsync(ISolutionSynchronizationService se var additionals = new List(); foreach (var documentObject in projectObject.AdditionalDocuments.ToDocumentObjects(service)) { - var documentInfo = await service.GetValueAsync(documentObject.Info).ConfigureAwait(false); + var documentInfo = await service.GetValueAsync(documentObject.Info).ConfigureAwait(false); var text = await service.GetValueAsync(documentObject.Text).ConfigureAwait(false); // TODO: do we need version? diff --git a/src/Workspaces/Remote/Core/Services/SolutionService.cs b/src/Workspaces/Remote/Core/Services/SolutionService.cs index f5ae898d57b..07fd67d687c 100644 --- a/src/Workspaces/Remote/Core/Services/SolutionService.cs +++ b/src/Workspaces/Remote/Core/Services/SolutionService.cs @@ -80,13 +80,13 @@ private async Task CreateSolutionAsync(Checksum solutionChecksum, Canc var solutionChecksumObject = await _assetService.GetAssetAsync(solutionChecksum, cancellationToken).ConfigureAwait(false); var workspace = new AdhocWorkspace(RoslynServices.HostServices, workspaceKind: WorkspaceKind_RemoteWorkspace); - var solutionInfo = await _assetService.GetAssetAsync(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false); + var solutionInfo = await _assetService.GetAssetAsync(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false); var projects = new List(); foreach (var projectChecksum in solutionChecksumObject.Projects) { var projectSnapshot = await _assetService.GetAssetAsync(projectChecksum, cancellationToken).ConfigureAwait(false); - var projectInfo = await _assetService.GetAssetAsync(projectSnapshot.Info, cancellationToken).ConfigureAwait(false); + var projectInfo = await _assetService.GetAssetAsync(projectSnapshot.Info, cancellationToken).ConfigureAwait(false); if (!workspace.Services.IsSupported(projectInfo.Language)) { // only add project our workspace supports. @@ -98,7 +98,7 @@ private async Task CreateSolutionAsync(Checksum solutionChecksum, Canc foreach (var documentChecksum in projectSnapshot.Documents) { var documentSnapshot = await _assetService.GetAssetAsync(documentChecksum, cancellationToken).ConfigureAwait(false); - var documentInfo = await _assetService.GetAssetAsync(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); + var documentInfo = await _assetService.GetAssetAsync(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); var textLoader = TextLoader.From( TextAndVersion.Create( @@ -151,7 +151,7 @@ private async Task CreateSolutionAsync(Checksum solutionChecksum, Canc cancellationToken.ThrowIfCancellationRequested(); var documentSnapshot = await _assetService.GetAssetAsync(documentChecksum, cancellationToken).ConfigureAwait(false); - var documentInfo = await _assetService.GetAssetAsync(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); + var documentInfo = await _assetService.GetAssetAsync(documentSnapshot.Info, cancellationToken).ConfigureAwait(false); var textLoader = TextLoader.From( TextAndVersion.Create( diff --git a/src/Workspaces/Remote/ServiceHub/Diagnostics/DiagnosticResultSerializer.cs b/src/Workspaces/Remote/ServiceHub/Diagnostics/DiagnosticResultSerializer.cs index d3790d611a8..3ba68de8f44 100644 --- a/src/Workspaces/Remote/ServiceHub/Diagnostics/DiagnosticResultSerializer.cs +++ b/src/Workspaces/Remote/ServiceHub/Diagnostics/DiagnosticResultSerializer.cs @@ -7,7 +7,7 @@ using System.Threading; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics.Telemetry; -using Microsoft.CodeAnalysis.Serialization; +using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Roslyn.Utilities; @@ -112,7 +112,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap>(); for (var i = 0; i < count; i++) { - var documentId = Serializer.DeserializeDocumentId(reader, cancellationToken); + var documentId = DocumentId.ReadFrom(reader); var diagnostics = serializer.ReadFrom(reader, project.GetDocument(documentId), cancellationToken); map.Add(documentId, GetOrDefault(diagnostics)); -- GitLab