提交 446629fa 编写于 作者: H Heejae Chang

removed serializedSolution/Project/DocumentInfo and rolled them into Solution/Project/DocumentInfo

上级 475c6258
......@@ -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;
}
......
......@@ -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<T>(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:
......
......@@ -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
/// </summary>
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<string>();
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<string>();
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<byte>());
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<byte>());
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<byte>());
var debugName = reader.ReadString();
return DocumentId.CreateFromSerialized(projectId, guid, debugName);
}
}
}
......@@ -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);
......
// 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);
}
}
}
......@@ -63,5 +63,17 @@ public static Checksum Create<T>(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);
}
}
}
}
......@@ -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.
/// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class DocumentId : IEquatable<DocumentId>
public sealed class DocumentId : IEquatable<DocumentId>, 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);
}
}
}
// 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; }
/// <summary>
/// The Id of the document.
/// </summary>
public DocumentId Id { get; }
public DocumentId Id => Attributes.Id;
/// <summary>
/// The name of the document.
/// </summary>
public string Name { get; }
public string Name => Attributes.Name;
/// <summary>
/// The names of the logical nested folders the document is contained in.
/// </summary>
public IReadOnlyList<string> Folders { get; }
public IReadOnlyList<string> Folders => Attributes.Folders;
/// <summary>
/// The kind of the source code.
/// </summary>
public SourceCodeKind SourceCodeKind { get; }
public SourceCodeKind SourceCodeKind => Attributes.SourceCodeKind;
/// <summary>
/// The file path of the document.
/// </summary>
public string FilePath { get; }
public string FilePath => Attributes.FilePath;
/// <summary>
/// A loader that can retrieve the document text.
/// True if the document is a side effect of the build.
/// </summary>
public TextLoader TextLoader { get; }
public bool IsGenerated => Attributes.IsGenerated;
/// <summary>
/// True if the document is a side effect of the build.
/// A loader that can retrieve the document text.
/// </summary>
public bool IsGenerated { get; }
public TextLoader TextLoader { get; }
/// <summary>
/// Create a new instance of a <see cref="DocumentInfo"/>.
/// </summary>
private DocumentInfo(
DocumentId id,
string name,
IEnumerable<string> folders,
SourceCodeKind sourceCodeKind,
TextLoader loader,
string filePath,
bool isGenerated)
{
if (id == null)
private DocumentInfo(DocumentAttributes attributes, TextLoader loader)
{
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<string> folders = null,
Optional<SourceCodeKind> sourceCodeKind = default(Optional<SourceCodeKind>),
Optional<TextLoader> loader = default(Optional<TextLoader>),
Optional<string> filePath = default(Optional<string>))
{
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)
DocumentAttributes attributes = null,
Optional<TextLoader> loader = default(Optional<TextLoader>))
{
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<string> 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);
}
/// <summary>
/// type that contains information regarding this document itself but
/// no tree information such as document info
/// </summary>
internal class DocumentAttributes : IChecksummedObject, IObjectWritable
{
/// <summary>
/// The Id of the document.
/// </summary>
public DocumentId Id { get; }
/// <summary>
/// The name of the document.
/// </summary>
public string Name { get; }
/// <summary>
/// The names of the logical nested folders the document is contained in.
/// </summary>
public IReadOnlyList<string> Folders { get; }
/// <summary>
/// The kind of the source code.
/// </summary>
public SourceCodeKind SourceCodeKind { get; }
/// <summary>
/// The file path of the document.
/// </summary>
public string FilePath { get; }
/// <summary>
/// True if the document is a side effect of the build.
/// </summary>
public bool IsGenerated { get; }
public DocumentAttributes(
DocumentId id,
string name,
IEnumerable<string> 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<string> folders = null,
Optional<SourceCodeKind> sourceCodeKind = default(Optional<SourceCodeKind>),
Optional<string> filePath = default(Optional<string>),
Optional<bool> isGenerated = default(Optional<bool>))
{
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;
}
}
}
}
}
......@@ -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 <see cref="Project"/> across versions.
/// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class ProjectId : IEquatable<ProjectId>
public sealed class ProjectId : IEquatable<ProjectId>, 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);
}
}
}
......@@ -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; }
/// <summary>
/// The unique Id of the project.
/// </summary>
public ProjectId Id { get; }
public ProjectId Id => Attributes.Id;
/// <summary>
/// The version of the project.
/// </summary>
public VersionStamp Version { get; }
public VersionStamp Version => Attributes.Version;
/// <summary>
/// The name of the project. This may differ from the project's filename.
/// </summary>
public string Name { get; }
public string Name => Attributes.Name;
/// <summary>
/// The name of the assembly that this project will create, without file extension.
/// </summary>,
public string AssemblyName { get; }
public string AssemblyName => Attributes.AssemblyName;
/// <summary>
/// The language of the project.
/// </summary>
public string Language { get; }
public string Language => Attributes.Language;
/// <summary>
/// The path to the project file or null if there is no project file.
/// </summary>
public string FilePath { get; }
public string FilePath => Attributes.FilePath;
/// <summary>
/// The path to the output file (module or assembly).
/// </summary>
public string OutputFilePath { get; }
public string OutputFilePath => Attributes.OutputFilePath;
/// <summary>
/// True if this is a submission project for interactive sessions.
/// </summary>
public bool IsSubmission => Attributes.IsSubmission;
/// <summary>
/// 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.
/// </summary>
internal bool HasAllInformation => Attributes.HasAllInformation;
/// <summary>
/// The initial compilation options for the project, or null if the default options should be used.
......@@ -84,31 +99,13 @@ public sealed class ProjectInfo
/// </summary>
public IReadOnlyList<DocumentInfo> AdditionalDocuments { get; }
/// <summary>
/// True if this is a submission project for interactive sessions.
/// </summary>
public bool IsSubmission { get; }
/// <summary>
/// Type of the host object.
/// </summary>
public Type HostObjectType { get; }
/// <summary>
/// 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.
/// </summary>
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<DocumentInfo> documents,
......@@ -116,47 +113,17 @@ public sealed class ProjectInfo
IEnumerable<MetadataReference> metadataReferences,
IEnumerable<AnalyzerReference> analyzerReferences,
IEnumerable<DocumentInfo> additionalDocuments,
bool isSubmission,
Type hostObjectType,
bool hasAllInformation)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (assemblyName == null)
Type hostObjectType)
{
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;
}
/// <summary>
......@@ -182,6 +149,7 @@ public sealed class ProjectInfo
bool hasAllInformation)
{
return new ProjectInfo(
new ProjectAttributes(
id,
version,
name,
......@@ -189,6 +157,8 @@ public sealed class ProjectInfo
language,
filePath,
outputFilePath,
isSubmission,
hasAllInformation),
compilationOptions,
parseOptions,
documents,
......@@ -196,9 +166,7 @@ public sealed class ProjectInfo
metadataReferences,
analyzerReferences,
additionalDocuments,
isSubmission,
hostObjectType,
hasAllInformation);
hostObjectType);
}
/// <summary>
......@@ -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<string> filePath = default(Optional<string>),
Optional<string> outputPath = default(Optional<string>),
ProjectAttributes attributes = null,
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
IEnumerable<DocumentInfo> documents = null,
......@@ -244,57 +206,33 @@ public sealed class ProjectInfo
IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null,
IEnumerable<DocumentInfo> additionalDocuments = null,
Optional<bool> isSubmission = default(Optional<bool>),
Optional<Type> hostObjectType = default(Optional<Type>),
Optional<bool> hasAllInformation = default(Optional<bool>))
Optional<Type> hostObjectType = default(Optional<Type>))
{
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<DocumentInfo> documents)
{
return this.With(documents: documents.ToImmutableReadOnlyListOrEmpty());
return With(documents: documents.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithAdditionalDocuments(IEnumerable<DocumentInfo> 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<ProjectReference> projectReferences)
{
return this.With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty());
return With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithMetadataReferences(IEnumerable<MetadataReference> metadataReferences)
{
return this.With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty());
return With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty());
}
public ProjectInfo WithAnalyzerReferences(IEnumerable<AnalyzerReference> 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 : "");
}
/// <summary>
/// type that contains information regarding this project itself but
/// no tree information such as document info
/// </summary>
internal class ProjectAttributes : IChecksummedObject, IObjectWritable
{
/// <summary>
/// The unique Id of the project.
/// </summary>
public ProjectId Id { get; }
/// <summary>
/// The version of the project.
/// </summary>
public VersionStamp Version { get; }
/// <summary>
/// The name of the project. This may differ from the project's filename.
/// </summary>
public string Name { get; }
/// <summary>
/// The name of the assembly that this project will create, without file extension.
/// </summary>,
public string AssemblyName { get; }
/// <summary>
/// The language of the project.
/// </summary>
public string Language { get; }
/// <summary>
/// The path to the project file or null if there is no project file.
/// </summary>
public string FilePath { get; }
/// <summary>
/// The path to the output file (module or assembly).
/// </summary>
public string OutputFilePath { get; }
/// <summary>
/// True if this is a submission project for interactive sessions.
/// </summary>
public bool IsSubmission { get; }
/// <summary>
/// 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.
/// </summary>
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<string> filePath = default(Optional<string>),
Optional<string> outputPath = default(Optional<string>),
Optional<bool> isSubmission = default(Optional<bool>),
Optional<bool> hasAllInformation = default(Optional<bool>))
{
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;
}
}
}
}
}
......@@ -31,7 +31,7 @@ private async Task<ProjectStateChecksums> 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;
......
// 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
{
/// <summary>
/// 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.
/// </summary>
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<string> Folders;
public readonly SourceCodeKind SourceCodeKind;
public readonly string FilePath;
public readonly bool IsGenerated;
public SerializedDocumentInfo(DocumentId id, string name, IReadOnlyList<string> folders, SourceCodeKind sourceCodeKind, string filePath, bool isGenerated)
{
Id = id;
Name = name;
Folders = folders;
SourceCodeKind = sourceCodeKind;
FilePath = filePath;
IsGenerated = isGenerated;
}
}
}
......@@ -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.
/// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class SolutionId : IEquatable<SolutionId>
public sealed class SolutionId : IEquatable<SolutionId>, IObjectWritable
{
/// <summary>
/// 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);
}
}
}
// 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
/// </summary>
public sealed class SolutionInfo
{
internal SolutionAttributes Attributes { get; }
/// <summary>
/// The unique Id of the solution.
/// </summary>
public SolutionId Id { get; }
public SolutionId Id => Attributes.Id;
/// <summary>
/// The version of the solution.
/// </summary>
public VersionStamp Version { get; }
public VersionStamp Version => Attributes.Version;
/// <summary>
/// The path to the solution file, or null if there is no solution file.
/// </summary>
public string FilePath { get; }
public string FilePath => Attributes.FilePath;
/// <summary>
/// A list of projects initially associated with the solution.
/// </summary>
public IReadOnlyList<ProjectInfo> Projects { get; }
private SolutionInfo(
SolutionId id,
VersionStamp version,
string filePath,
IEnumerable<ProjectInfo> projects)
private SolutionInfo(SolutionAttributes attributes, IEnumerable<ProjectInfo> projects)
{
this.Id = id;
this.Version = version;
this.FilePath = filePath;
this.Projects = projects.ToImmutableReadOnlyListOrEmpty();
Attributes = attributes;
Projects = projects.ToImmutableReadOnlyListOrEmpty();
}
/// <summary>
......@@ -51,7 +49,106 @@ public sealed class SolutionInfo
string filePath = null,
IEnumerable<ProjectInfo> 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<ProjectInfo> 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<ProjectInfo> projects)
{
return With(projects: projects);
}
/// <summary>
/// type that contains information regarding this solution itself but
/// no tree information such as project info
/// </summary>
internal class SolutionAttributes : IChecksummedObject, IObjectWritable
{
/// <summary>
/// The unique Id of the solution.
/// </summary>
public SolutionId Id { get; }
/// <summary>
/// The version of the solution.
/// </summary>
public VersionStamp Version { get; }
/// <summary>
/// The path to the solution file, or null if there is no solution file.
/// </summary>
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;
}
}
}
}
}
......@@ -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<ProjectId> _projectIds;
private readonly ImmutableDictionary<ProjectId, ProjectState> _projectIdToProjectStateMap;
private readonly ImmutableDictionary<string, ImmutableArray<DocumentId>> _linkedFilesMap;
private readonly VersionStamp _version;
private readonly Lazy<VersionStamp> _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<ProjectId> projectIds,
ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap,
ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap,
ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap,
ProjectDependencyGraph dependencyGraph,
VersionStamp version,
Lazy<VersionStamp> lazyLatestProjectVersion,
ValueSource<SolutionStateChecksums> lazyChecksums)
Lazy<VersionStamp> 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<SolutionStateChecksums>(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<ProjectId, ProjectState>.Empty,
projectIdToTrackerMap: ImmutableDictionary<ProjectId, CompilationTracker>.Empty,
linkedFilesMap: ImmutableDictionary.Create<string, ImmutableArray<DocumentId>>(StringComparer.OrdinalIgnoreCase),
dependencyGraph: ProjectDependencyGraph.Empty,
lazyLatestProjectVersion: null,
lazyChecksums: null)
lazyLatestProjectVersion: null)
{
// this is for the very first solution state ever created
_lazyLatestProjectVersion = new Lazy<VersionStamp>(() => ComputeLatestProjectVersion());
......@@ -127,6 +116,8 @@ private VersionStamp ComputeLatestProjectVersion()
return latestVersion;
}
public SolutionInfo SolutionInfo => _solutionInfo;
public ImmutableDictionary<ProjectId, ProjectState> ProjectStates => _projectIdToProjectStateMap;
public int WorkspaceVersion => _workspaceVersion;
......@@ -154,17 +145,17 @@ private VersionStamp ComputeLatestProjectVersion()
/// <summary>
/// The Id of the solution. Multiple solution instances may share the same Id.
/// </summary>
public SolutionId Id => _id;
public SolutionId Id => _solutionInfo.Id;
/// <summary>
/// The path to the solution file or null if there is no solution file.
/// </summary>
public string FilePath => _filePath;
public string FilePath => _solutionInfo.FilePath;
/// <summary>
/// The solution version. This equates to the solution file's version.
/// </summary>
public VersionStamp Version => _version;
public VersionStamp Version => _solutionInfo.Version;
/// <summary>
/// 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<ProjectId> projectIds = null,
ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null,
ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null,
ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap = null,
ProjectDependencyGraph dependencyGraph = null,
VersionStamp? version = default(VersionStamp?),
Lazy<VersionStamp> lazyLatestProjectVersion = null,
ValueSource<SolutionStateChecksums> lazyChecksums = null)
Lazy<VersionStamp> 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<VersionStamp>(() => 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<string, ImmutableArray<DocumentId>> CreateLinkedFilesMapWithRemovedProject(ProjectState projectState)
......
......@@ -29,7 +29,7 @@ private async Task<SolutionStateChecksums> 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));
......
......@@ -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))
......
......@@ -29,7 +29,7 @@ private async Task<DocumentStateChecksums> 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);
......
......@@ -988,7 +988,6 @@
<Compile Include="Workspace\Solution\IDocumentTextDifferencingService.cs" />
<Compile Include="Workspace\Solution\MetadataReferenceManager.cs" />
<Compile Include="Workspace\Solution\ProjectState_Checksum.cs" />
<Compile Include="Workspace\Solution\SerializedInfos.cs" />
<Compile Include="Workspace\Solution\SolutionState.CompilationTranslationAction.cs" />
<Compile Include="Workspace\Solution\SolutionState.CompilationTranslationAction.Actions.cs" />
<Compile Include="Workspace\Solution\SolutionState.CompilationTracker.State.cs" />
......
......@@ -38,7 +38,7 @@ internal static Solution CreateFullSolution(HostServices hostServices = null)
internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, SolutionStateChecksums solutionObject)
{
await VerifyAssetSerializationAsync<SerializedSolutionInfo>(
await VerifyAssetSerializationAsync<SolutionInfo.SolutionAttributes>(
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<SerializedProjectInfo>(
var info = await VerifyAssetSerializationAsync<ProjectInfo.ProjectAttributes>(
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<SerializedDocumentInfo>(
var info = await VerifyAssetSerializationAsync<DocumentInfo.DocumentAttributes>(
service, documentObject.Info, WellKnownSynchronizationKinds.DocumentInfo,
(v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false);
......
......@@ -471,12 +471,12 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var workspace = new AdhocWorkspace();
var solutionObject = await service.GetValueAsync<SolutionStateChecksums>(syncScope.SolutionChecksum);
var solutionInfo = await service.GetValueAsync<SerializedSolutionInfo>(solutionObject.Info).ConfigureAwait(false);
var solutionInfo = await service.GetValueAsync<SolutionInfo.SolutionAttributes>(solutionObject.Info).ConfigureAwait(false);
var projects = new List<ProjectInfo>();
foreach (var projectObject in solutionObject.Projects.ToProjectObjects(service))
{
var projectInfo = await service.GetValueAsync<SerializedProjectInfo>(projectObject.Info).ConfigureAwait(false);
var projectInfo = await service.GetValueAsync<ProjectInfo.ProjectAttributes>(projectObject.Info).ConfigureAwait(false);
if (!workspace.Services.IsSupported(projectInfo.Language))
{
continue;
......@@ -485,7 +485,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var documents = new List<DocumentInfo>();
foreach (var documentObject in projectObject.Documents.ToDocumentObjects(service))
{
var documentInfo = await service.GetValueAsync<SerializedDocumentInfo>(documentObject.Info).ConfigureAwait(false);
var documentInfo = await service.GetValueAsync<DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false);
var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);
// TODO: do we need version?
......@@ -524,7 +524,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var additionals = new List<DocumentInfo>();
foreach (var documentObject in projectObject.AdditionalDocuments.ToDocumentObjects(service))
{
var documentInfo = await service.GetValueAsync<SerializedDocumentInfo>(documentObject.Info).ConfigureAwait(false);
var documentInfo = await service.GetValueAsync<DocumentInfo.DocumentAttributes>(documentObject.Info).ConfigureAwait(false);
var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);
// TODO: do we need version?
......
......@@ -80,13 +80,13 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var solutionChecksumObject = await _assetService.GetAssetAsync<SolutionStateChecksums>(solutionChecksum, cancellationToken).ConfigureAwait(false);
var workspace = new AdhocWorkspace(RoslynServices.HostServices, workspaceKind: WorkspaceKind_RemoteWorkspace);
var solutionInfo = await _assetService.GetAssetAsync<SerializedSolutionInfo>(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false);
var solutionInfo = await _assetService.GetAssetAsync<SolutionInfo.SolutionAttributes>(solutionChecksumObject.Info, cancellationToken).ConfigureAwait(false);
var projects = new List<ProjectInfo>();
foreach (var projectChecksum in solutionChecksumObject.Projects)
{
var projectSnapshot = await _assetService.GetAssetAsync<ProjectStateChecksums>(projectChecksum, cancellationToken).ConfigureAwait(false);
var projectInfo = await _assetService.GetAssetAsync<SerializedProjectInfo>(projectSnapshot.Info, cancellationToken).ConfigureAwait(false);
var projectInfo = await _assetService.GetAssetAsync<ProjectInfo.ProjectAttributes>(projectSnapshot.Info, cancellationToken).ConfigureAwait(false);
if (!workspace.Services.IsSupported(projectInfo.Language))
{
// only add project our workspace supports.
......@@ -98,7 +98,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
foreach (var documentChecksum in projectSnapshot.Documents)
{
var documentSnapshot = await _assetService.GetAssetAsync<DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false);
var documentInfo = await _assetService.GetAssetAsync<SerializedDocumentInfo>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false);
var documentInfo = await _assetService.GetAssetAsync<DocumentInfo.DocumentAttributes>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false);
var textLoader = TextLoader.From(
TextAndVersion.Create(
......@@ -151,7 +151,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
cancellationToken.ThrowIfCancellationRequested();
var documentSnapshot = await _assetService.GetAssetAsync<DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false);
var documentInfo = await _assetService.GetAssetAsync<SerializedDocumentInfo>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false);
var documentInfo = await _assetService.GetAssetAsync<DocumentInfo.DocumentAttributes>(documentSnapshot.Info, cancellationToken).ConfigureAwait(false);
var textLoader = TextLoader.From(
TextAndVersion.Create(
......
......@@ -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<st
writer.WriteInt32(diagnostics.Count);
foreach (var kv in diagnostics)
{
Serializer.SerializeDocumentId(kv.Key, writer, cancellationToken);
kv.Key.WriteTo(writer);
serializer.WriteTo(writer, kv.Value, cancellationToken);
}
}
......@@ -127,7 +127,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
var map = ImmutableDictionary.CreateBuilder<DocumentId, ImmutableArray<DiagnosticData>>();
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));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册