提交 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) ...@@ -62,17 +62,17 @@ public static string GetWellKnownSynchronizationKind(this object value)
return WellKnownSynchronizationKinds.AnalyzerReferences; return WellKnownSynchronizationKinds.AnalyzerReferences;
} }
if (value is SerializedSolutionInfo) if (value is SolutionInfo.SolutionAttributes)
{ {
return WellKnownSynchronizationKinds.SolutionInfo; return WellKnownSynchronizationKinds.SolutionInfo;
} }
if (value is SerializedProjectInfo) if (value is ProjectInfo.ProjectAttributes)
{ {
return WellKnownSynchronizationKinds.ProjectInfo; return WellKnownSynchronizationKinds.ProjectInfo;
} }
if (value is SerializedDocumentInfo) if (value is DocumentInfo.DocumentAttributes)
{ {
return WellKnownSynchronizationKinds.DocumentInfo; return WellKnownSynchronizationKinds.DocumentInfo;
} }
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Execution; using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -52,9 +51,6 @@ public Checksum CreateChecksum(object value, CancellationToken cancellationToken ...@@ -52,9 +51,6 @@ public Checksum CreateChecksum(object value, CancellationToken cancellationToken
case WellKnownSynchronizationKinds.Null: case WellKnownSynchronizationKinds.Null:
return Checksum.Null; return Checksum.Null;
case WellKnownSynchronizationKinds.SolutionInfo:
case WellKnownSynchronizationKinds.ProjectInfo:
case WellKnownSynchronizationKinds.DocumentInfo:
case WellKnownSynchronizationKinds.CompilationOptions: case WellKnownSynchronizationKinds.CompilationOptions:
case WellKnownSynchronizationKinds.ParseOptions: case WellKnownSynchronizationKinds.ParseOptions:
case WellKnownSynchronizationKinds.ProjectReference: case WellKnownSynchronizationKinds.ProjectReference:
...@@ -98,15 +94,9 @@ public void Serialize(object value, ObjectWriter writer, CancellationToken cance ...@@ -98,15 +94,9 @@ public void Serialize(object value, ObjectWriter writer, CancellationToken cance
return; return;
case WellKnownSynchronizationKinds.SolutionInfo: case WellKnownSynchronizationKinds.SolutionInfo:
SerializeSerializedSolutionInfo((SerializedSolutionInfo)value, writer, cancellationToken);
return;
case WellKnownSynchronizationKinds.ProjectInfo: case WellKnownSynchronizationKinds.ProjectInfo:
SerializeSerializedProjectInfo((SerializedProjectInfo)value, writer, cancellationToken);
return;
case WellKnownSynchronizationKinds.DocumentInfo: case WellKnownSynchronizationKinds.DocumentInfo:
SerializeSerializedDocumentInfo((SerializedDocumentInfo)value, writer, cancellationToken); ((IObjectWritable)value).WriteTo(writer);
return; return;
case WellKnownSynchronizationKinds.CompilationOptions: case WellKnownSynchronizationKinds.CompilationOptions:
...@@ -164,11 +154,11 @@ public T Deserialize<T>(string kind, ObjectReader reader, CancellationToken canc ...@@ -164,11 +154,11 @@ public T Deserialize<T>(string kind, ObjectReader reader, CancellationToken canc
return (T)(object)DeserializeChecksumWithChildren(reader, cancellationToken); return (T)(object)DeserializeChecksumWithChildren(reader, cancellationToken);
case WellKnownSynchronizationKinds.SolutionInfo: case WellKnownSynchronizationKinds.SolutionInfo:
return (T)(object)DeserializeSerializedSolutionInfo(reader, cancellationToken); return (T)(object)SolutionInfo.SolutionAttributes.ReadFrom(reader);
case WellKnownSynchronizationKinds.ProjectInfo: case WellKnownSynchronizationKinds.ProjectInfo:
return (T)(object)DeserializeSerializedProjectInfo(reader, cancellationToken); return (T)(object)ProjectInfo.ProjectAttributes.ReadFrom(reader);
case WellKnownSynchronizationKinds.DocumentInfo: case WellKnownSynchronizationKinds.DocumentInfo:
return (T)(object)DeserializeSerializedDocumentInfo(reader, cancellationToken); return (T)(object)DocumentInfo.DocumentAttributes.ReadFrom(reader);
case WellKnownSynchronizationKinds.CompilationOptions: case WellKnownSynchronizationKinds.CompilationOptions:
return (T)(object)DeserializeCompilationOptions(reader, cancellationToken); return (T)(object)DeserializeCompilationOptions(reader, cancellationToken);
case WellKnownSynchronizationKinds.ParseOptions: case WellKnownSynchronizationKinds.ParseOptions:
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Execution; using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -19,91 +20,6 @@ namespace Microsoft.CodeAnalysis.Serialization ...@@ -19,91 +20,6 @@ namespace Microsoft.CodeAnalysis.Serialization
/// </summary> /// </summary>
internal partial class Serializer 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) public void SerializeSourceText(ITemporaryStorageWithName storage, SourceText text, ObjectWriter writer, CancellationToken cancellationToken)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
...@@ -205,7 +121,7 @@ public void SerializeProjectReference(ProjectReference reference, ObjectWriter w ...@@ -205,7 +121,7 @@ public void SerializeProjectReference(ProjectReference reference, ObjectWriter w
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
SerializeProjectId(reference.ProjectId, writer, cancellationToken); reference.ProjectId.WriteTo(writer);
writer.WriteValue(reference.Aliases.ToArray()); writer.WriteValue(reference.Aliases.ToArray());
writer.WriteBoolean(reference.EmbedInteropTypes); writer.WriteBoolean(reference.EmbedInteropTypes);
} }
...@@ -214,7 +130,7 @@ private ProjectReference DeserializeProjectReference(ObjectReader reader, Cancel ...@@ -214,7 +130,7 @@ private ProjectReference DeserializeProjectReference(ObjectReader reader, Cancel
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var projectId = DeserializeProjectId(reader, cancellationToken); var projectId = ProjectId.ReadFrom(reader);
var aliases = reader.ReadArray<string>(); var aliases = reader.ReadArray<string>();
var embedInteropTypes = reader.ReadBoolean(); var embedInteropTypes = reader.ReadBoolean();
...@@ -244,51 +160,5 @@ private AnalyzerReference DeserializeAnalyzerReference(ObjectReader reader, Canc ...@@ -244,51 +160,5 @@ private AnalyzerReference DeserializeAnalyzerReference(ObjectReader reader, Canc
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
return _hostSerializationService.ReadAnalyzerReferenceFrom(reader, cancellationToken); 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 ...@@ -18,9 +18,9 @@ internal static class WellKnownSynchronizationKinds
public const string MetadataReferences = nameof(MetadataReferenceChecksumCollection); public const string MetadataReferences = nameof(MetadataReferenceChecksumCollection);
public const string AnalyzerReferences = nameof(AnalyzerReferenceChecksumCollection); public const string AnalyzerReferences = nameof(AnalyzerReferenceChecksumCollection);
public const string SolutionInfo = nameof(SerializedSolutionInfo); public const string SolutionInfo = nameof(CodeAnalysis.SolutionInfo.SolutionAttributes);
public const string ProjectInfo = nameof(SerializedProjectInfo); public const string ProjectInfo = nameof(CodeAnalysis.ProjectInfo.ProjectAttributes);
public const string DocumentInfo = nameof(SerializedDocumentInfo); public const string DocumentInfo = nameof(CodeAnalysis.DocumentInfo.DocumentAttributes);
public const string CompilationOptions = nameof(CompilationOptions); public const string CompilationOptions = nameof(CompilationOptions);
public const string ParseOptions = nameof(ParseOptions); 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. // 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 namespace Microsoft.CodeAnalysis.Shared.Extensions
{ {
internal static class SolutionExtensions internal static class SolutionExtensions
{ {
public static SourceCodeKind GetSourceCodeKind(this TextDocumentState state) public static void WriteTo(this IObjectWritable @object, ObjectWriter writer)
{
// these can just be abstract property
return (state as DocumentState)?.SourceCodeKind ?? SourceCodeKind.Regular;
}
public static bool IsGenerated(this TextDocumentState state)
{ {
// these can just be abstract property @object.WriteTo(writer);
return (state as DocumentState)?.IsGenerated ?? false;
} }
} }
} }
...@@ -63,5 +63,17 @@ public static Checksum Create<T>(T value, string kind, Serializer serializer) ...@@ -63,5 +63,17 @@ public static Checksum Create<T>(T value, string kind, Serializer serializer)
return Create(stream); 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 @@ ...@@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
...@@ -12,7 +13,7 @@ namespace Microsoft.CodeAnalysis ...@@ -12,7 +13,7 @@ namespace Microsoft.CodeAnalysis
/// workspace. /// workspace.
/// </summary> /// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")] [DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class DocumentId : IEquatable<DocumentId> public sealed class DocumentId : IEquatable<DocumentId>, IObjectWritable
{ {
public ProjectId ProjectId { get; } public ProjectId ProjectId { get; }
public Guid Id { get; } public Guid Id { get; }
...@@ -96,5 +97,23 @@ public override int GetHashCode() ...@@ -96,5 +97,23 @@ public override int GetHashCode()
{ {
return !(left == right); 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. // 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;
using System.Diagnostics;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
...@@ -13,70 +15,50 @@ namespace Microsoft.CodeAnalysis ...@@ -13,70 +15,50 @@ namespace Microsoft.CodeAnalysis
[DebuggerDisplay("{GetDebuggerDisplay() , nq}")] [DebuggerDisplay("{GetDebuggerDisplay() , nq}")]
public sealed class DocumentInfo public sealed class DocumentInfo
{ {
internal DocumentAttributes Attributes { get; }
/// <summary> /// <summary>
/// The Id of the document. /// The Id of the document.
/// </summary> /// </summary>
public DocumentId Id { get; } public DocumentId Id => Attributes.Id;
/// <summary> /// <summary>
/// The name of the document. /// The name of the document.
/// </summary> /// </summary>
public string Name { get; } public string Name => Attributes.Name;
/// <summary> /// <summary>
/// The names of the logical nested folders the document is contained in. /// The names of the logical nested folders the document is contained in.
/// </summary> /// </summary>
public IReadOnlyList<string> Folders { get; } public IReadOnlyList<string> Folders => Attributes.Folders;
/// <summary> /// <summary>
/// The kind of the source code. /// The kind of the source code.
/// </summary> /// </summary>
public SourceCodeKind SourceCodeKind { get; } public SourceCodeKind SourceCodeKind => Attributes.SourceCodeKind;
/// <summary> /// <summary>
/// The file path of the document. /// The file path of the document.
/// </summary> /// </summary>
public string FilePath { get; } public string FilePath => Attributes.FilePath;
/// <summary> /// <summary>
/// A loader that can retrieve the document text. /// True if the document is a side effect of the build.
/// </summary> /// </summary>
public TextLoader TextLoader { get; } public bool IsGenerated => Attributes.IsGenerated;
/// <summary> /// <summary>
/// True if the document is a side effect of the build. /// A loader that can retrieve the document text.
/// </summary> /// </summary>
public bool IsGenerated { get; } public TextLoader TextLoader { get; }
/// <summary> /// <summary>
/// Create a new instance of a <see cref="DocumentInfo"/>. /// Create a new instance of a <see cref="DocumentInfo"/>.
/// </summary> /// </summary>
private DocumentInfo( private DocumentInfo(DocumentAttributes attributes, TextLoader loader)
DocumentId id,
string name,
IEnumerable<string> folders,
SourceCodeKind sourceCodeKind,
TextLoader loader,
string filePath,
bool isGenerated)
{
if (id == null)
{ {
throw new ArgumentNullException(nameof(id)); Attributes = attributes;
} TextLoader = loader;
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;
} }
public static DocumentInfo Create( public static DocumentInfo Create(
...@@ -88,70 +70,186 @@ public sealed class DocumentInfo ...@@ -88,70 +70,186 @@ public sealed class DocumentInfo
string filePath = null, string filePath = null,
bool isGenerated = false) 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( private DocumentInfo With(
DocumentId id = null, DocumentAttributes attributes = null,
string name = null, Optional<TextLoader> loader = default(Optional<TextLoader>))
IEnumerable<string> folders = null, {
Optional<SourceCodeKind> sourceCodeKind = default(Optional<SourceCodeKind>), var newAttributes = attributes ?? Attributes;
Optional<TextLoader> loader = default(Optional<TextLoader>), var newLoader = loader.HasValue ? loader.Value : TextLoader;
Optional<string> filePath = default(Optional<string>))
{ if (newAttributes == Attributes && newLoader == TextLoader)
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)
{ {
return this; return this;
} }
return new DocumentInfo(newId, newName, newFolders, newSourceCodeKind, newLoader, newFilePath, this.IsGenerated); return new DocumentInfo(newAttributes, newLoader);
} }
public DocumentInfo WithId(DocumentId id) public DocumentInfo WithId(DocumentId id)
{ {
return this.With(id: id); return With(attributes: Attributes.With(id: id));
} }
public DocumentInfo WithName(string name) public DocumentInfo WithName(string name)
{ {
return this.With(name: name); return this.With(attributes: Attributes.With(name: name));
} }
public DocumentInfo WithFolders(IEnumerable<string> folders) 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) public DocumentInfo WithSourceCodeKind(SourceCodeKind kind)
{ {
return this.With(sourceCodeKind: kind); return this.With(attributes: Attributes.With(sourceCodeKind: kind));
} }
public DocumentInfo WithTextLoader(TextLoader loader) public DocumentInfo WithTextLoader(TextLoader loader)
{ {
return this.With(loader: loader); return With(loader: loader);
} }
public DocumentInfo WithFilePath(string filePath) public DocumentInfo WithFilePath(string filePath)
{ {
return this.With(filePath: filePath); return this.With(attributes: Attributes.With(filePath: filePath));
} }
private string GetDebuggerDisplay() private string GetDebuggerDisplay()
{ {
return (FilePath == null) ? (nameof(Name) + " = " + Name) : (nameof(FilePath) + " = " + FilePath); 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 @@ ...@@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
{ {
...@@ -10,7 +11,7 @@ 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. /// An identifier that can be used to refer to the same <see cref="Project"/> across versions.
/// </summary> /// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")] [DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class ProjectId : IEquatable<ProjectId> public sealed class ProjectId : IEquatable<ProjectId>, IObjectWritable
{ {
private readonly string _debugName; private readonly string _debugName;
...@@ -82,5 +83,19 @@ public override int GetHashCode() ...@@ -82,5 +83,19 @@ public override int GetHashCode()
{ {
return this.Id.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 @@ ...@@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
...@@ -14,40 +15,54 @@ namespace Microsoft.CodeAnalysis ...@@ -14,40 +15,54 @@ namespace Microsoft.CodeAnalysis
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")] [DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
public sealed class ProjectInfo public sealed class ProjectInfo
{ {
internal ProjectAttributes Attributes { get; }
/// <summary> /// <summary>
/// The unique Id of the project. /// The unique Id of the project.
/// </summary> /// </summary>
public ProjectId Id { get; } public ProjectId Id => Attributes.Id;
/// <summary> /// <summary>
/// The version of the project. /// The version of the project.
/// </summary> /// </summary>
public VersionStamp Version { get; } public VersionStamp Version => Attributes.Version;
/// <summary> /// <summary>
/// The name of the project. This may differ from the project's filename. /// The name of the project. This may differ from the project's filename.
/// </summary> /// </summary>
public string Name { get; } public string Name => Attributes.Name;
/// <summary> /// <summary>
/// The name of the assembly that this project will create, without file extension. /// The name of the assembly that this project will create, without file extension.
/// </summary>, /// </summary>,
public string AssemblyName { get; } public string AssemblyName => Attributes.AssemblyName;
/// <summary> /// <summary>
/// The language of the project. /// The language of the project.
/// </summary> /// </summary>
public string Language { get; } public string Language => Attributes.Language;
/// <summary> /// <summary>
/// The path to the project file or null if there is no project file. /// The path to the project file or null if there is no project file.
/// </summary> /// </summary>
public string FilePath { get; } public string FilePath => Attributes.FilePath;
/// <summary> /// <summary>
/// The path to the output file (module or assembly). /// The path to the output file (module or assembly).
/// </summary> /// </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> /// <summary>
/// The initial compilation options for the project, or null if the default options should be used. /// The initial compilation options for the project, or null if the default options should be used.
...@@ -84,31 +99,13 @@ public sealed class ProjectInfo ...@@ -84,31 +99,13 @@ public sealed class ProjectInfo
/// </summary> /// </summary>
public IReadOnlyList<DocumentInfo> AdditionalDocuments { get; } public IReadOnlyList<DocumentInfo> AdditionalDocuments { get; }
/// <summary>
/// True if this is a submission project for interactive sessions.
/// </summary>
public bool IsSubmission { get; }
/// <summary> /// <summary>
/// Type of the host object. /// Type of the host object.
/// </summary> /// </summary>
public Type HostObjectType { get; } 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( private ProjectInfo(
ProjectId id, ProjectAttributes attributes,
VersionStamp version,
string name,
string assemblyName,
string language,
string filePath,
string outputFilePath,
CompilationOptions compilationOptions, CompilationOptions compilationOptions,
ParseOptions parseOptions, ParseOptions parseOptions,
IEnumerable<DocumentInfo> documents, IEnumerable<DocumentInfo> documents,
...@@ -116,47 +113,17 @@ public sealed class ProjectInfo ...@@ -116,47 +113,17 @@ public sealed class ProjectInfo
IEnumerable<MetadataReference> metadataReferences, IEnumerable<MetadataReference> metadataReferences,
IEnumerable<AnalyzerReference> analyzerReferences, IEnumerable<AnalyzerReference> analyzerReferences,
IEnumerable<DocumentInfo> additionalDocuments, IEnumerable<DocumentInfo> additionalDocuments,
bool isSubmission, Type hostObjectType)
Type hostObjectType,
bool hasAllInformation)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (assemblyName == null)
{ {
throw new ArgumentNullException(nameof(assemblyName)); Attributes = attributes;
} CompilationOptions = compilationOptions;
ParseOptions = parseOptions;
if (language == null) Documents = documents.ToImmutableReadOnlyListOrEmpty();
{ ProjectReferences = projectReferences.ToImmutableReadOnlyListOrEmpty();
throw new ArgumentNullException(nameof(language)); MetadataReferences = metadataReferences.ToImmutableReadOnlyListOrEmpty();
} AnalyzerReferences = analyzerReferences.ToImmutableReadOnlyListOrEmpty();
AdditionalDocuments = additionalDocuments.ToImmutableReadOnlyListOrEmpty();
this.Id = id; HostObjectType = hostObjectType;
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;
} }
/// <summary> /// <summary>
...@@ -182,6 +149,7 @@ public sealed class ProjectInfo ...@@ -182,6 +149,7 @@ public sealed class ProjectInfo
bool hasAllInformation) bool hasAllInformation)
{ {
return new ProjectInfo( return new ProjectInfo(
new ProjectAttributes(
id, id,
version, version,
name, name,
...@@ -189,6 +157,8 @@ public sealed class ProjectInfo ...@@ -189,6 +157,8 @@ public sealed class ProjectInfo
language, language,
filePath, filePath,
outputFilePath, outputFilePath,
isSubmission,
hasAllInformation),
compilationOptions, compilationOptions,
parseOptions, parseOptions,
documents, documents,
...@@ -196,9 +166,7 @@ public sealed class ProjectInfo ...@@ -196,9 +166,7 @@ public sealed class ProjectInfo
metadataReferences, metadataReferences,
analyzerReferences, analyzerReferences,
additionalDocuments, additionalDocuments,
isSubmission, hostObjectType);
hostObjectType,
hasAllInformation);
} }
/// <summary> /// <summary>
...@@ -230,13 +198,7 @@ public sealed class ProjectInfo ...@@ -230,13 +198,7 @@ public sealed class ProjectInfo
} }
private ProjectInfo With( private ProjectInfo With(
ProjectId id = null, ProjectAttributes attributes = 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>),
CompilationOptions compilationOptions = null, CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null, ParseOptions parseOptions = null,
IEnumerable<DocumentInfo> documents = null, IEnumerable<DocumentInfo> documents = null,
...@@ -244,57 +206,33 @@ public sealed class ProjectInfo ...@@ -244,57 +206,33 @@ public sealed class ProjectInfo
IEnumerable<MetadataReference> metadataReferences = null, IEnumerable<MetadataReference> metadataReferences = null,
IEnumerable<AnalyzerReference> analyzerReferences = null, IEnumerable<AnalyzerReference> analyzerReferences = null,
IEnumerable<DocumentInfo> additionalDocuments = null, IEnumerable<DocumentInfo> additionalDocuments = null,
Optional<bool> isSubmission = default(Optional<bool>), Optional<Type> hostObjectType = default(Optional<Type>))
Optional<Type> hostObjectType = default(Optional<Type>),
Optional<bool> hasAllInformation = default(Optional<bool>))
{ {
var newId = id ?? this.Id; var newAttributes = attributes ?? Attributes;
var newVersion = version.HasValue ? version.Value : this.Version; var newCompilationOptions = compilationOptions ?? CompilationOptions;
var newName = name ?? this.Name; var newParseOptions = parseOptions ?? ParseOptions;
var newAssemblyName = assemblyName ?? this.AssemblyName; var newDocuments = documents ?? Documents;
var newLanguage = language ?? this.Language; var newProjectReferences = projectReferences ?? ProjectReferences;
var newFilepath = filePath.HasValue ? filePath.Value : this.FilePath; var newMetadataReferences = metadataReferences ?? MetadataReferences;
var newOutputPath = outputPath.HasValue ? outputPath.Value : this.OutputFilePath; var newAnalyzerReferences = analyzerReferences ?? AnalyzerReferences;
var newCompilationOptions = compilationOptions ?? this.CompilationOptions; var newAdditionalDocuments = additionalDocuments ?? AdditionalDocuments;
var newParseOptions = parseOptions ?? this.ParseOptions; var newHostObjectType = hostObjectType.HasValue ? hostObjectType.Value : HostObjectType;
var newDocuments = documents ?? this.Documents;
var newProjectReferences = projectReferences ?? this.ProjectReferences; if (newAttributes == Attributes &&
var newMetadataReferences = metadataReferences ?? this.MetadataReferences; newCompilationOptions == CompilationOptions &&
var newAnalyzerReferences = analyzerReferences ?? this.AnalyzerReferences; newParseOptions == ParseOptions &&
var newAdditionalDocuments = additionalDocuments ?? this.AdditionalDocuments; newDocuments == Documents &&
var newIsSubmission = isSubmission.HasValue ? isSubmission.Value : this.IsSubmission; newProjectReferences == ProjectReferences &&
var newHostObjectType = hostObjectType.HasValue ? hostObjectType.Value : this.HostObjectType; newMetadataReferences == MetadataReferences &&
var newHasAllInformation = hasAllInformation.HasValue ? hasAllInformation.Value : this.HasAllInformation; newAnalyzerReferences == AnalyzerReferences &&
newAdditionalDocuments == AdditionalDocuments &&
if (newId == this.Id && newHostObjectType == HostObjectType)
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)
{ {
return this; return this;
} }
return new ProjectInfo( return new ProjectInfo(
newId, newAttributes,
newVersion,
newName,
newAssemblyName,
newLanguage,
newFilepath,
newOutputPath,
newCompilationOptions, newCompilationOptions,
newParseOptions, newParseOptions,
newDocuments, newDocuments,
...@@ -302,79 +240,266 @@ public sealed class ProjectInfo ...@@ -302,79 +240,266 @@ public sealed class ProjectInfo
newMetadataReferences, newMetadataReferences,
newAnalyzerReferences, newAnalyzerReferences,
newAdditionalDocuments, newAdditionalDocuments,
newIsSubmission, newHostObjectType);
newHostObjectType,
newHasAllInformation);
} }
public ProjectInfo WithDocuments(IEnumerable<DocumentInfo> documents) public ProjectInfo WithDocuments(IEnumerable<DocumentInfo> documents)
{ {
return this.With(documents: documents.ToImmutableReadOnlyListOrEmpty()); return With(documents: documents.ToImmutableReadOnlyListOrEmpty());
} }
public ProjectInfo WithAdditionalDocuments(IEnumerable<DocumentInfo> additionalDocuments) public ProjectInfo WithAdditionalDocuments(IEnumerable<DocumentInfo> additionalDocuments)
{ {
return this.With(additionalDocuments: additionalDocuments.ToImmutableReadOnlyListOrEmpty()); return With(additionalDocuments: additionalDocuments.ToImmutableReadOnlyListOrEmpty());
} }
public ProjectInfo WithVersion(VersionStamp version) public ProjectInfo WithVersion(VersionStamp version)
{ {
return this.With(version: version); return With(attributes: Attributes.With(version: version));
} }
public ProjectInfo WithName(string name) public ProjectInfo WithName(string name)
{ {
return this.With(name: name); return With(attributes: Attributes.With(name: name));
} }
public ProjectInfo WithFilePath(string filePath) public ProjectInfo WithFilePath(string filePath)
{ {
return this.With(filePath: filePath); return With(attributes: Attributes.With(filePath: filePath));
} }
public ProjectInfo WithAssemblyName(string assemblyName) public ProjectInfo WithAssemblyName(string assemblyName)
{ {
return this.With(assemblyName: assemblyName); return With(attributes: Attributes.With(assemblyName: assemblyName));
} }
public ProjectInfo WithOutputFilePath(string outputFilePath) public ProjectInfo WithOutputFilePath(string outputFilePath)
{ {
return this.With(outputPath: outputFilePath); return With(attributes: Attributes.With(outputPath: outputFilePath));
} }
public ProjectInfo WithCompilationOptions(CompilationOptions compilationOptions) public ProjectInfo WithCompilationOptions(CompilationOptions compilationOptions)
{ {
return this.With(compilationOptions: compilationOptions); return With(compilationOptions: compilationOptions);
} }
public ProjectInfo WithParseOptions(ParseOptions parseOptions) public ProjectInfo WithParseOptions(ParseOptions parseOptions)
{ {
return this.With(parseOptions: parseOptions); return With(parseOptions: parseOptions);
} }
public ProjectInfo WithProjectReferences(IEnumerable<ProjectReference> projectReferences) public ProjectInfo WithProjectReferences(IEnumerable<ProjectReference> projectReferences)
{ {
return this.With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty()); return With(projectReferences: projectReferences.ToImmutableReadOnlyListOrEmpty());
} }
public ProjectInfo WithMetadataReferences(IEnumerable<MetadataReference> metadataReferences) public ProjectInfo WithMetadataReferences(IEnumerable<MetadataReference> metadataReferences)
{ {
return this.With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty()); return With(metadataReferences: metadataReferences.ToImmutableReadOnlyListOrEmpty());
} }
public ProjectInfo WithAnalyzerReferences(IEnumerable<AnalyzerReference> analyzerReferences) public ProjectInfo WithAnalyzerReferences(IEnumerable<AnalyzerReference> analyzerReferences)
{ {
return this.With(analyzerReferences: analyzerReferences.ToImmutableReadOnlyListOrEmpty()); return With(analyzerReferences: analyzerReferences.ToImmutableReadOnlyListOrEmpty());
} }
internal ProjectInfo WithHasAllInformation(bool hasAllInformation) internal ProjectInfo WithHasAllInformation(bool hasAllInformation)
{ {
return this.With(hasAllInformation: hasAllInformation); return With(attributes: Attributes.With(hasAllInformation: hasAllInformation));
} }
internal string GetDebuggerDisplay() internal string GetDebuggerDisplay()
{ {
return nameof(ProjectInfo) + " " + Name + (!string.IsNullOrWhiteSpace(FilePath) ? " " + FilePath : ""); 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 ...@@ -31,7 +31,7 @@ private async Task<ProjectStateChecksums> ComputeChecksumsAsync(CancellationToke
var serializer = new Serializer(_solutionServices.Workspace.Services); 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 compilationOptionsChecksum = SupportsCompilation ? serializer.CreateChecksum(CompilationOptions, cancellationToken) : Checksum.Null;
var parseOptionsChecksum = SupportsCompilation ? serializer.CreateChecksum(ParseOptions, 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 @@ ...@@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
{ {
...@@ -10,7 +11,7 @@ namespace Microsoft.CodeAnalysis ...@@ -10,7 +11,7 @@ namespace Microsoft.CodeAnalysis
/// An identifier that can be used to refer to the same Solution across versions. /// An identifier that can be used to refer to the same Solution across versions.
/// </summary> /// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(),nq}")] [DebuggerDisplay("{GetDebuggerDisplay(),nq}")]
public sealed class SolutionId : IEquatable<SolutionId> public sealed class SolutionId : IEquatable<SolutionId>, IObjectWritable
{ {
/// <summary> /// <summary>
/// The unique id of the solution. /// The unique id of the solution.
...@@ -79,5 +80,19 @@ public override int GetHashCode() ...@@ -79,5 +80,19 @@ public override int GetHashCode()
{ {
return this.Id.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. // 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 System.Collections.Generic;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
...@@ -10,36 +12,32 @@ namespace Microsoft.CodeAnalysis ...@@ -10,36 +12,32 @@ namespace Microsoft.CodeAnalysis
/// </summary> /// </summary>
public sealed class SolutionInfo public sealed class SolutionInfo
{ {
internal SolutionAttributes Attributes { get; }
/// <summary> /// <summary>
/// The unique Id of the solution. /// The unique Id of the solution.
/// </summary> /// </summary>
public SolutionId Id { get; } public SolutionId Id => Attributes.Id;
/// <summary> /// <summary>
/// The version of the solution. /// The version of the solution.
/// </summary> /// </summary>
public VersionStamp Version { get; } public VersionStamp Version => Attributes.Version;
/// <summary> /// <summary>
/// The path to the solution file, or null if there is no solution file. /// The path to the solution file, or null if there is no solution file.
/// </summary> /// </summary>
public string FilePath { get; } public string FilePath => Attributes.FilePath;
/// <summary> /// <summary>
/// A list of projects initially associated with the solution. /// A list of projects initially associated with the solution.
/// </summary> /// </summary>
public IReadOnlyList<ProjectInfo> Projects { get; } public IReadOnlyList<ProjectInfo> Projects { get; }
private SolutionInfo( private SolutionInfo(SolutionAttributes attributes, IEnumerable<ProjectInfo> projects)
SolutionId id,
VersionStamp version,
string filePath,
IEnumerable<ProjectInfo> projects)
{ {
this.Id = id; Attributes = attributes;
this.Version = version; Projects = projects.ToImmutableReadOnlyListOrEmpty();
this.FilePath = filePath;
this.Projects = projects.ToImmutableReadOnlyListOrEmpty();
} }
/// <summary> /// <summary>
...@@ -51,7 +49,106 @@ public sealed class SolutionInfo ...@@ -51,7 +49,106 @@ public sealed class SolutionInfo
string filePath = null, string filePath = null,
IEnumerable<ProjectInfo> projects = 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 ...@@ -30,13 +30,11 @@ internal partial class SolutionState
// the version of the workspace this solution is from // the version of the workspace this solution is from
private readonly int _workspaceVersion; private readonly int _workspaceVersion;
private readonly SolutionInfo _solutionInfo;
private readonly SolutionServices _solutionServices; private readonly SolutionServices _solutionServices;
private readonly SolutionId _id;
private readonly string _filePath;
private readonly IReadOnlyList<ProjectId> _projectIds; private readonly IReadOnlyList<ProjectId> _projectIds;
private readonly ImmutableDictionary<ProjectId, ProjectState> _projectIdToProjectStateMap; private readonly ImmutableDictionary<ProjectId, ProjectState> _projectIdToProjectStateMap;
private readonly ImmutableDictionary<string, ImmutableArray<DocumentId>> _linkedFilesMap; private readonly ImmutableDictionary<string, ImmutableArray<DocumentId>> _linkedFilesMap;
private readonly VersionStamp _version;
private readonly Lazy<VersionStamp> _lazyLatestProjectVersion; private readonly Lazy<VersionStamp> _lazyLatestProjectVersion;
private readonly ProjectDependencyGraph _dependencyGraph; private readonly ProjectDependencyGraph _dependencyGraph;
...@@ -50,32 +48,26 @@ internal partial class SolutionState ...@@ -50,32 +48,26 @@ internal partial class SolutionState
BranchId branchId, BranchId branchId,
int workspaceVersion, int workspaceVersion,
SolutionServices solutionServices, SolutionServices solutionServices,
SolutionId id, SolutionInfo solutionInfo,
string filePath,
IEnumerable<ProjectId> projectIds, IEnumerable<ProjectId> projectIds,
ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap, ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap,
ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap, ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap,
ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap, ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap,
ProjectDependencyGraph dependencyGraph, ProjectDependencyGraph dependencyGraph,
VersionStamp version, Lazy<VersionStamp> lazyLatestProjectVersion)
Lazy<VersionStamp> lazyLatestProjectVersion,
ValueSource<SolutionStateChecksums> lazyChecksums)
{ {
_branchId = branchId; _branchId = branchId;
_workspaceVersion = workspaceVersion; _workspaceVersion = workspaceVersion;
_id = id;
_filePath = filePath;
_solutionServices = solutionServices; _solutionServices = solutionServices;
_solutionInfo = solutionInfo;
_projectIds = projectIds.ToImmutableReadOnlyListOrEmpty(); _projectIds = projectIds.ToImmutableReadOnlyListOrEmpty();
_projectIdToProjectStateMap = idToProjectStateMap; _projectIdToProjectStateMap = idToProjectStateMap;
_projectIdToTrackerMap = projectIdToTrackerMap; _projectIdToTrackerMap = projectIdToTrackerMap;
_linkedFilesMap = linkedFilesMap; _linkedFilesMap = linkedFilesMap;
_dependencyGraph = dependencyGraph; _dependencyGraph = dependencyGraph;
_version = version;
_lazyLatestProjectVersion = lazyLatestProjectVersion; _lazyLatestProjectVersion = lazyLatestProjectVersion;
// for now, let it re-calculate if anything changed. // when solution state is changed, we re-calcuate its checksum
// TODO: optimize this so that we only re-calcuate checksums that are actually changed
_lazyChecksums = new AsyncLazy<SolutionStateChecksums>(ComputeChecksumsAsync, cacheResult: true); _lazyChecksums = new AsyncLazy<SolutionStateChecksums>(ComputeChecksumsAsync, cacheResult: true);
CheckInvariants(); CheckInvariants();
...@@ -88,16 +80,13 @@ internal partial class SolutionState ...@@ -88,16 +80,13 @@ internal partial class SolutionState
workspace.PrimaryBranchId, workspace.PrimaryBranchId,
workspaceVersion: 0, workspaceVersion: 0,
solutionServices: new SolutionServices(workspace), solutionServices: new SolutionServices(workspace),
id: info.Id, solutionInfo: info,
filePath: info.FilePath,
version: info.Version,
projectIds: null, projectIds: null,
idToProjectStateMap: ImmutableDictionary<ProjectId, ProjectState>.Empty, idToProjectStateMap: ImmutableDictionary<ProjectId, ProjectState>.Empty,
projectIdToTrackerMap: ImmutableDictionary<ProjectId, CompilationTracker>.Empty, projectIdToTrackerMap: ImmutableDictionary<ProjectId, CompilationTracker>.Empty,
linkedFilesMap: ImmutableDictionary.Create<string, ImmutableArray<DocumentId>>(StringComparer.OrdinalIgnoreCase), linkedFilesMap: ImmutableDictionary.Create<string, ImmutableArray<DocumentId>>(StringComparer.OrdinalIgnoreCase),
dependencyGraph: ProjectDependencyGraph.Empty, dependencyGraph: ProjectDependencyGraph.Empty,
lazyLatestProjectVersion: null, lazyLatestProjectVersion: null)
lazyChecksums: null)
{ {
// this is for the very first solution state ever created // this is for the very first solution state ever created
_lazyLatestProjectVersion = new Lazy<VersionStamp>(() => ComputeLatestProjectVersion()); _lazyLatestProjectVersion = new Lazy<VersionStamp>(() => ComputeLatestProjectVersion());
...@@ -127,6 +116,8 @@ private VersionStamp ComputeLatestProjectVersion() ...@@ -127,6 +116,8 @@ private VersionStamp ComputeLatestProjectVersion()
return latestVersion; return latestVersion;
} }
public SolutionInfo SolutionInfo => _solutionInfo;
public ImmutableDictionary<ProjectId, ProjectState> ProjectStates => _projectIdToProjectStateMap; public ImmutableDictionary<ProjectId, ProjectState> ProjectStates => _projectIdToProjectStateMap;
public int WorkspaceVersion => _workspaceVersion; public int WorkspaceVersion => _workspaceVersion;
...@@ -154,17 +145,17 @@ private VersionStamp ComputeLatestProjectVersion() ...@@ -154,17 +145,17 @@ private VersionStamp ComputeLatestProjectVersion()
/// <summary> /// <summary>
/// The Id of the solution. Multiple solution instances may share the same Id. /// The Id of the solution. Multiple solution instances may share the same Id.
/// </summary> /// </summary>
public SolutionId Id => _id; public SolutionId Id => _solutionInfo.Id;
/// <summary> /// <summary>
/// The path to the solution file or null if there is no solution file. /// The path to the solution file or null if there is no solution file.
/// </summary> /// </summary>
public string FilePath => _filePath; public string FilePath => _solutionInfo.FilePath;
/// <summary> /// <summary>
/// The solution version. This equates to the solution file's version. /// The solution version. This equates to the solution file's version.
/// </summary> /// </summary>
public VersionStamp Version => _version; public VersionStamp Version => _solutionInfo.Version;
/// <summary> /// <summary>
/// A list of all the ids for all the projects contained by the solution. /// A list of all the ids for all the projects contained by the solution.
...@@ -181,53 +172,48 @@ private void CheckInvariants() ...@@ -181,53 +172,48 @@ private void CheckInvariants()
} }
private SolutionState Branch( private SolutionState Branch(
SolutionInfo solutionInfo = null,
IEnumerable<ProjectId> projectIds = null, IEnumerable<ProjectId> projectIds = null,
ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null, ImmutableDictionary<ProjectId, ProjectState> idToProjectStateMap = null,
ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null, ImmutableDictionary<ProjectId, CompilationTracker> projectIdToTrackerMap = null,
ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap = null, ImmutableDictionary<string, ImmutableArray<DocumentId>> linkedFilesMap = null,
ProjectDependencyGraph dependencyGraph = null, ProjectDependencyGraph dependencyGraph = null,
VersionStamp? version = default(VersionStamp?), Lazy<VersionStamp> lazyLatestProjectVersion = null)
Lazy<VersionStamp> lazyLatestProjectVersion = null,
ValueSource<SolutionStateChecksums> lazyChecksums = null)
{ {
var branchId = GetBranchId(); var branchId = GetBranchId();
solutionInfo = solutionInfo ?? _solutionInfo;
projectIds = projectIds ?? _projectIds; projectIds = projectIds ?? _projectIds;
idToProjectStateMap = idToProjectStateMap ?? _projectIdToProjectStateMap; idToProjectStateMap = idToProjectStateMap ?? _projectIdToProjectStateMap;
projectIdToTrackerMap = projectIdToTrackerMap ?? _projectIdToTrackerMap; projectIdToTrackerMap = projectIdToTrackerMap ?? _projectIdToTrackerMap;
linkedFilesMap = linkedFilesMap ?? _linkedFilesMap; linkedFilesMap = linkedFilesMap ?? _linkedFilesMap;
dependencyGraph = dependencyGraph ?? _dependencyGraph; dependencyGraph = dependencyGraph ?? _dependencyGraph;
version = version.HasValue ? version.Value : _version;
lazyLatestProjectVersion = lazyLatestProjectVersion ?? _lazyLatestProjectVersion; lazyLatestProjectVersion = lazyLatestProjectVersion ?? _lazyLatestProjectVersion;
lazyChecksums = lazyChecksums ?? _lazyChecksums;
if (branchId == _branchId && if (branchId == _branchId &&
solutionInfo == _solutionInfo &&
projectIds == _projectIds && projectIds == _projectIds &&
idToProjectStateMap == _projectIdToProjectStateMap && idToProjectStateMap == _projectIdToProjectStateMap &&
projectIdToTrackerMap == _projectIdToTrackerMap && projectIdToTrackerMap == _projectIdToTrackerMap &&
linkedFilesMap == _linkedFilesMap && linkedFilesMap == _linkedFilesMap &&
dependencyGraph == _dependencyGraph && dependencyGraph == _dependencyGraph &&
version == _version && lazyLatestProjectVersion == _lazyLatestProjectVersion)
lazyLatestProjectVersion == _lazyLatestProjectVersion &&
lazyChecksums == _lazyChecksums)
{ {
return this; return this;
} }
return new SolutionState( return new SolutionState(
branchId, branchId,
_workspaceVersion, _workspaceVersion,
_solutionServices, _solutionServices,
_id, solutionInfo,
_filePath,
projectIds, projectIds,
idToProjectStateMap, idToProjectStateMap,
projectIdToTrackerMap, projectIdToTrackerMap,
linkedFilesMap, linkedFilesMap,
dependencyGraph, dependencyGraph,
version.Value, lazyLatestProjectVersion);
lazyLatestProjectVersion,
lazyChecksums);
} }
private SolutionState CreatePrimarySolution( private SolutionState CreatePrimarySolution(
...@@ -246,16 +232,13 @@ private void CheckInvariants() ...@@ -246,16 +232,13 @@ private void CheckInvariants()
branchId, branchId,
workspaceVersion, workspaceVersion,
services, services,
_id, _solutionInfo,
_filePath,
_projectIds, _projectIds,
_projectIdToProjectStateMap, _projectIdToProjectStateMap,
_projectIdToTrackerMap, _projectIdToTrackerMap,
_linkedFilesMap, _linkedFilesMap,
_dependencyGraph, _dependencyGraph,
_version, _lazyLatestProjectVersion);
_lazyLatestProjectVersion,
_lazyChecksums);
} }
private BranchId GetBranchId() private BranchId GetBranchId()
...@@ -428,6 +411,10 @@ private CompilationTracker GetCompilationTracker(ProjectId projectId) ...@@ -428,6 +411,10 @@ private CompilationTracker GetCompilationTracker(ProjectId projectId)
private SolutionState AddProject(ProjectId projectId, ProjectState projectState) 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 newProjectIds = _projectIds.ToImmutableArray().Add(projectId);
var newStateMap = _projectIdToProjectStateMap.Add(projectId, projectState); var newStateMap = _projectIdToProjectStateMap.Add(projectId, projectState);
var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap); var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap);
...@@ -435,12 +422,12 @@ private SolutionState AddProject(ProjectId projectId, ProjectState projectState) ...@@ -435,12 +422,12 @@ private SolutionState AddProject(ProjectId projectId, ProjectState projectState)
var newLinkedFilesMap = CreateLinkedFilesMapWithAddedProject(newStateMap[projectId]); var newLinkedFilesMap = CreateLinkedFilesMapWithAddedProject(newStateMap[projectId]);
return this.Branch( return this.Branch(
solutionInfo: newSolutionInfo,
projectIds: newProjectIds, projectIds: newProjectIds,
idToProjectStateMap: newStateMap, idToProjectStateMap: newStateMap,
projectIdToTrackerMap: newTrackerMap, projectIdToTrackerMap: newTrackerMap,
linkedFilesMap: newLinkedFilesMap, linkedFilesMap: newLinkedFilesMap,
dependencyGraph: newDependencyGraph, dependencyGraph: newDependencyGraph,
version: this.Version.GetNewerVersion(), // changed project list so, increment version.
lazyLatestProjectVersion: new Lazy<VersionStamp>(() => projectState.Version)); // this is the newest! lazyLatestProjectVersion: new Lazy<VersionStamp>(() => projectState.Version)); // this is the newest!
} }
...@@ -520,6 +507,10 @@ public SolutionState RemoveProject(ProjectId projectId) ...@@ -520,6 +507,10 @@ public SolutionState RemoveProject(ProjectId projectId)
CheckContainsProject(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 newProjectIds = _projectIds.ToImmutableArray().Remove(projectId);
var newStateMap = _projectIdToProjectStateMap.Remove(projectId); var newStateMap = _projectIdToProjectStateMap.Remove(projectId);
var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap); var newDependencyGraph = CreateDependencyGraph(newProjectIds, newStateMap);
...@@ -527,12 +518,12 @@ public SolutionState RemoveProject(ProjectId projectId) ...@@ -527,12 +518,12 @@ public SolutionState RemoveProject(ProjectId projectId)
var newLinkedFilesMap = CreateLinkedFilesMapWithRemovedProject(_projectIdToProjectStateMap[projectId]); var newLinkedFilesMap = CreateLinkedFilesMapWithRemovedProject(_projectIdToProjectStateMap[projectId]);
return this.Branch( return this.Branch(
solutionInfo: newSolutionInfo,
projectIds: newProjectIds, projectIds: newProjectIds,
idToProjectStateMap: newStateMap, idToProjectStateMap: newStateMap,
projectIdToTrackerMap: newTrackerMap.Remove(projectId), projectIdToTrackerMap: newTrackerMap.Remove(projectId),
linkedFilesMap: newLinkedFilesMap, linkedFilesMap: newLinkedFilesMap,
dependencyGraph: newDependencyGraph, dependencyGraph: newDependencyGraph);
version: this.Version.GetNewerVersion()); // changed project list, so increment version
} }
private ImmutableDictionary<string, ImmutableArray<DocumentId>> CreateLinkedFilesMapWithRemovedProject(ProjectState projectState) private ImmutableDictionary<string, ImmutableArray<DocumentId>> CreateLinkedFilesMapWithRemovedProject(ProjectState projectState)
......
...@@ -29,7 +29,7 @@ private async Task<SolutionStateChecksums> ComputeChecksumsAsync(CancellationTok ...@@ -29,7 +29,7 @@ private async Task<SolutionStateChecksums> ComputeChecksumsAsync(CancellationTok
var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id].GetChecksumAsync(cancellationToken)); var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id].GetChecksumAsync(cancellationToken));
var serializer = new Serializer(_solutionServices.Workspace.Services); 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); var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);
return new SolutionStateChecksums(infoChecksum, new ProjectChecksumCollection(projectChecksums)); return new SolutionStateChecksums(infoChecksum, new ProjectChecksumCollection(projectChecksums));
......
...@@ -47,7 +47,7 @@ public SolutionStateChecksums With(Checksum infoChecksum = null, ProjectChecksum ...@@ -47,7 +47,7 @@ public SolutionStateChecksums With(Checksum infoChecksum = null, ProjectChecksum
if (searchingChecksumsLeft.Remove(Info)) if (searchingChecksumsLeft.Remove(Info))
{ {
result[Info] = new SerializedSolutionInfo(state.Id, state.Version, state.FilePath); result[Info] = state.SolutionInfo.Attributes;
} }
if (searchingChecksumsLeft.Remove(Projects.Checksum)) if (searchingChecksumsLeft.Remove(Projects.Checksum))
...@@ -152,7 +152,7 @@ public ProjectStateChecksums(params object[] children) : base(nameof(ProjectStat ...@@ -152,7 +152,7 @@ public ProjectStateChecksums(params object[] children) : base(nameof(ProjectStat
if (searchingChecksumsLeft.Remove(Info)) 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)) if (searchingChecksumsLeft.Remove(CompilationOptions))
...@@ -286,7 +286,7 @@ public DocumentStateChecksums With(Checksum infoChecksum = null, Checksum textCh ...@@ -286,7 +286,7 @@ public DocumentStateChecksums With(Checksum infoChecksum = null, Checksum textCh
if (searchingChecksumsLeft.Remove(Info)) 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)) if (searchingChecksumsLeft.Remove(Text))
......
...@@ -29,7 +29,7 @@ private async Task<DocumentStateChecksums> ComputeChecksumsAsync(CancellationTok ...@@ -29,7 +29,7 @@ private async Task<DocumentStateChecksums> ComputeChecksumsAsync(CancellationTok
var serializer = new Serializer(solutionServices.Workspace.Services); 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); var textChecksum = serializer.CreateChecksum(await textTask.ConfigureAwait(false), cancellationToken);
return new DocumentStateChecksums(infoChecksum, textChecksum); return new DocumentStateChecksums(infoChecksum, textChecksum);
......
...@@ -988,7 +988,6 @@ ...@@ -988,7 +988,6 @@
<Compile Include="Workspace\Solution\IDocumentTextDifferencingService.cs" /> <Compile Include="Workspace\Solution\IDocumentTextDifferencingService.cs" />
<Compile Include="Workspace\Solution\MetadataReferenceManager.cs" /> <Compile Include="Workspace\Solution\MetadataReferenceManager.cs" />
<Compile Include="Workspace\Solution\ProjectState_Checksum.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.cs" />
<Compile Include="Workspace\Solution\SolutionState.CompilationTranslationAction.Actions.cs" /> <Compile Include="Workspace\Solution\SolutionState.CompilationTranslationAction.Actions.cs" />
<Compile Include="Workspace\Solution\SolutionState.CompilationTracker.State.cs" /> <Compile Include="Workspace\Solution\SolutionState.CompilationTracker.State.cs" />
......
...@@ -38,7 +38,7 @@ internal static Solution CreateFullSolution(HostServices hostServices = null) ...@@ -38,7 +38,7 @@ internal static Solution CreateFullSolution(HostServices hostServices = null)
internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, SolutionStateChecksums solutionObject) internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, SolutionStateChecksums solutionObject)
{ {
await VerifyAssetSerializationAsync<SerializedSolutionInfo>( await VerifyAssetSerializationAsync<SolutionInfo.SolutionAttributes>(
service, solutionObject.Info, WellKnownSynchronizationKinds.SolutionInfo, service, solutionObject.Info, WellKnownSynchronizationKinds.SolutionInfo,
(v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); (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 ...@@ -51,7 +51,7 @@ internal static async Task VerifyAssetAsync(ISolutionSynchronizationService serv
internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, ProjectStateChecksums projectObject) 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, service, projectObject.Info, WellKnownSynchronizationKinds.ProjectInfo,
(v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); (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 ...@@ -99,7 +99,7 @@ internal static async Task VerifyAssetAsync(ISolutionSynchronizationService serv
internal static async Task VerifyAssetAsync(ISolutionSynchronizationService service, DocumentStateChecksums documentObject) 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, service, documentObject.Info, WellKnownSynchronizationKinds.DocumentInfo,
(v, k, s) => SolutionAsset.Create(s.CreateChecksum(v, CancellationToken.None), v, s)).ConfigureAwait(false); (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 ...@@ -471,12 +471,12 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var workspace = new AdhocWorkspace(); var workspace = new AdhocWorkspace();
var solutionObject = await service.GetValueAsync<SolutionStateChecksums>(syncScope.SolutionChecksum); 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>(); var projects = new List<ProjectInfo>();
foreach (var projectObject in solutionObject.Projects.ToProjectObjects(service)) 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)) if (!workspace.Services.IsSupported(projectInfo.Language))
{ {
continue; continue;
...@@ -485,7 +485,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se ...@@ -485,7 +485,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var documents = new List<DocumentInfo>(); var documents = new List<DocumentInfo>();
foreach (var documentObject in projectObject.Documents.ToDocumentObjects(service)) 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); var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);
// TODO: do we need version? // TODO: do we need version?
...@@ -524,7 +524,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se ...@@ -524,7 +524,7 @@ private async Task<Solution> GetSolutionAsync(ISolutionSynchronizationService se
var additionals = new List<DocumentInfo>(); var additionals = new List<DocumentInfo>();
foreach (var documentObject in projectObject.AdditionalDocuments.ToDocumentObjects(service)) 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); var text = await service.GetValueAsync<SourceText>(documentObject.Text).ConfigureAwait(false);
// TODO: do we need version? // TODO: do we need version?
......
...@@ -80,13 +80,13 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc ...@@ -80,13 +80,13 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
var solutionChecksumObject = await _assetService.GetAssetAsync<SolutionStateChecksums>(solutionChecksum, cancellationToken).ConfigureAwait(false); var solutionChecksumObject = await _assetService.GetAssetAsync<SolutionStateChecksums>(solutionChecksum, cancellationToken).ConfigureAwait(false);
var workspace = new AdhocWorkspace(RoslynServices.HostServices, workspaceKind: WorkspaceKind_RemoteWorkspace); 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>(); var projects = new List<ProjectInfo>();
foreach (var projectChecksum in solutionChecksumObject.Projects) foreach (var projectChecksum in solutionChecksumObject.Projects)
{ {
var projectSnapshot = await _assetService.GetAssetAsync<ProjectStateChecksums>(projectChecksum, cancellationToken).ConfigureAwait(false); 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)) if (!workspace.Services.IsSupported(projectInfo.Language))
{ {
// only add project our workspace supports. // only add project our workspace supports.
...@@ -98,7 +98,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc ...@@ -98,7 +98,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
foreach (var documentChecksum in projectSnapshot.Documents) foreach (var documentChecksum in projectSnapshot.Documents)
{ {
var documentSnapshot = await _assetService.GetAssetAsync<DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false); 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( var textLoader = TextLoader.From(
TextAndVersion.Create( TextAndVersion.Create(
...@@ -151,7 +151,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc ...@@ -151,7 +151,7 @@ private async Task<Solution> CreateSolutionAsync(Checksum solutionChecksum, Canc
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var documentSnapshot = await _assetService.GetAssetAsync<DocumentStateChecksums>(documentChecksum, cancellationToken).ConfigureAwait(false); 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( var textLoader = TextLoader.From(
TextAndVersion.Create( TextAndVersion.Create(
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.Telemetry; using Microsoft.CodeAnalysis.Diagnostics.Telemetry;
using Microsoft.CodeAnalysis.Serialization; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Workspaces.Diagnostics; using Microsoft.CodeAnalysis.Workspaces.Diagnostics;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -112,7 +112,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st ...@@ -112,7 +112,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
writer.WriteInt32(diagnostics.Count); writer.WriteInt32(diagnostics.Count);
foreach (var kv in diagnostics) foreach (var kv in diagnostics)
{ {
Serializer.SerializeDocumentId(kv.Key, writer, cancellationToken); kv.Key.WriteTo(writer);
serializer.WriteTo(writer, kv.Value, cancellationToken); serializer.WriteTo(writer, kv.Value, cancellationToken);
} }
} }
...@@ -127,7 +127,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st ...@@ -127,7 +127,7 @@ public static void Serialize(ObjectWriter writer, DiagnosticAnalysisResultMap<st
var map = ImmutableDictionary.CreateBuilder<DocumentId, ImmutableArray<DiagnosticData>>(); var map = ImmutableDictionary.CreateBuilder<DocumentId, ImmutableArray<DiagnosticData>>();
for (var i = 0; i < count; i++) 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); var diagnostics = serializer.ReadFrom(reader, project.GetDocument(documentId), cancellationToken);
map.Add(documentId, GetOrDefault(diagnostics)); map.Add(documentId, GetOrDefault(diagnostics));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册