提交 f90258c5 编写于 作者: H Heejae Chang 提交者: GitHub

Merge pull request #15944 from heejaechang/streamJson

move StreamJsonRpc to latest version
......@@ -48,6 +48,7 @@ public static async Task<RemoteHostClient> CreateAsync(Workspace workspace, bool
_inprocServices = inprocServices;
_rpc = JsonRpc.Attach(stream, target: this);
_rpc.JsonSerializer.Converters.Add(AggregateJsonConverter.Instance);
// handle disconnected situation
_rpc.Disconnected += OnRpcDisconnected;
......
......@@ -20,7 +20,7 @@ internal abstract partial class AbstractNavigateToSearchService
{
var serializableResults = await session.InvokeAsync<SerializableNavigateToSearchResult[]>(
nameof(IRemoteNavigateToSearchService.SearchDocumentAsync),
SerializableDocumentId.Dehydrate(document),
document.Id,
searchPattern).ConfigureAwait(false);
return serializableResults.Select(r => r.Rehydrate(solution)).ToImmutableArray();
......@@ -37,7 +37,7 @@ internal abstract partial class AbstractNavigateToSearchService
{
var serializableResults = await session.InvokeAsync<SerializableNavigateToSearchResult[]>(
nameof(IRemoteNavigateToSearchService.SearchProjectAsync),
SerializableProjectId.Dehydrate(project.Id),
project.Id,
searchPattern).ConfigureAwait(false);
return serializableResults.Select(r => r.Rehydrate(solution)).ToImmutableArray();
......
......@@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.NavigateTo
{
internal interface IRemoteNavigateToSearchService
{
Task<SerializableNavigateToSearchResult[]> SearchDocumentAsync(SerializableDocumentId documentId, string searchPattern);
Task<SerializableNavigateToSearchResult[]> SearchProjectAsync(SerializableProjectId projectId, string searchPattern);
Task<SerializableNavigateToSearchResult[]> SearchDocumentAsync(DocumentId documentId, string searchPattern);
Task<SerializableNavigateToSearchResult[]> SearchProjectAsync(ProjectId projectId, string searchPattern);
}
}
......@@ -39,7 +39,7 @@ internal class SerializableNavigateToSearchResult
public NavigateToMatchKind MatchKind;
public bool IsCaseSensitive;
public string Name;
public SerializableTextSpan[] NameMatchSpans;
public TextSpan[] NameMatchSpans;
public string SecondarySort;
public string Summary;
......@@ -54,7 +54,7 @@ internal static SerializableNavigateToSearchResult Dehydrate(INavigateToSearchRe
MatchKind = result.MatchKind,
IsCaseSensitive = result.IsCaseSensitive,
Name = result.Name,
NameMatchSpans = result.NameMatchSpans.Select(SerializableTextSpan.Dehydrate).ToArray(),
NameMatchSpans = result.NameMatchSpans.ToArray(),
SecondarySort = result.SecondarySort,
Summary = result.Summary,
NavigableItem = SerializableNavigableItem.Dehydrate(result.NavigableItem)
......@@ -65,7 +65,7 @@ internal INavigateToSearchResult Rehydrate(Solution solution)
{
return new NavigateToSearchResult(
AdditionalInformation, Kind, MatchKind, IsCaseSensitive,
Name, NameMatchSpans.Select(s => s.Rehydrate()).ToImmutableArray(),
Name, NameMatchSpans.ToImmutableArray(),
SecondarySort, Summary, NavigableItem.Rehydrate(solution));
}
......@@ -83,7 +83,7 @@ private class NavigateToSearchResult : INavigateToSearchResult
public INavigableItem NavigableItem { get; }
public NavigateToSearchResult(
string additionalInformation, string kind, NavigateToMatchKind matchKind,
string additionalInformation, string kind, NavigateToMatchKind matchKind,
bool isCaseSensitive, string name, ImmutableArray<TextSpan> nameMatchSpans,
string secondarySort, string summary, INavigableItem navigableItem)
{
......@@ -110,8 +110,8 @@ internal class SerializableNavigableItem
public bool IsImplicitlyDeclared;
public SerializableDocumentId Document;
public SerializableTextSpan SourceSpan;
public DocumentId Document;
public TextSpan SourceSpan;
SerializableNavigableItem[] ChildItems;
......@@ -123,8 +123,8 @@ public static SerializableNavigableItem Dehydrate(INavigableItem item)
DisplayTaggedParts = SerializableTaggedText.Dehydrate(item.DisplayTaggedParts),
DisplayFileLocation = item.DisplayFileLocation,
IsImplicitlyDeclared = item.IsImplicitlyDeclared,
Document = SerializableDocumentId.Dehydrate(item.Document),
SourceSpan = SerializableTextSpan.Dehydrate(item.SourceSpan),
Document = item.Document.Id,
SourceSpan = item.SourceSpan,
ChildItems = SerializableNavigableItem.Dehydrate(item.ChildItems)
};
}
......@@ -142,8 +142,8 @@ public INavigableItem Rehydrate(Solution solution)
return new NavigableItem(
Glyph, DisplayTaggedParts.Select(p => p.Rehydrate()).ToImmutableArray(),
DisplayFileLocation, IsImplicitlyDeclared,
solution.GetDocument(Document.Rehydrate()),
SourceSpan.Rehydrate(),
solution.GetDocument(Document),
SourceSpan,
childItems);
}
......
......@@ -84,7 +84,7 @@ internal class VisualStudioDiagnosticAnalyzerExecutor : ICodeAnalysisDiagnosticA
var argument = new DiagnosticArguments(
analyzerDriver.AnalysisOptions.ReportSuppressedDiagnostics,
analyzerDriver.AnalysisOptions.LogAnalyzerExecutionTime,
project.Id, optionAsset.Checksum.ToArray(), hostChecksums, analyzerMap.Keys.ToArray());
project.Id, optionAsset.Checksum, hostChecksums, analyzerMap.Keys.ToArray());
// TODO: send telemetry on session
using (var session = await client.CreateCodeAnalysisServiceSessionAsync(solution, cancellationToken).ConfigureAwait(false))
......@@ -161,11 +161,11 @@ private void ReportAnalyzerExceptions(Project project, ImmutableDictionary<Diagn
}
}
private ImmutableArray<byte[]> GetHostAnalyzerReferences(
private ImmutableArray<Checksum> GetHostAnalyzerReferences(
ISolutionSynchronizationService snapshotService, string language, IEnumerable<AnalyzerReference> references, CancellationToken cancellationToken)
{
// TODO: cache this to somewhere
var builder = ImmutableArray.CreateBuilder<byte[]>();
var builder = ImmutableArray.CreateBuilder<Checksum>();
foreach (var reference in references)
{
var analyzers = reference.GetAnalyzers(language);
......@@ -178,7 +178,7 @@ private void ReportAnalyzerExceptions(Project project, ImmutableDictionary<Diagn
}
var asset = snapshotService.GetGlobalAsset(reference, cancellationToken);
builder.Add(asset.Checksum.ToArray());
builder.Add(asset.Checksum);
}
return builder.ToImmutable();
......
......@@ -124,7 +124,7 @@ private async Task SynchronizePrimaryWorkspaceAsync(CancellationToken cancellati
{
// ask remote host to sync initial asset
var checksum = await solution.State.GetChecksumAsync(cancellationToken).ConfigureAwait(false);
await session.InvokeAsync(WellKnownRemoteHostServices.RemoteHostService_SynchronizePrimaryWorkspaceAsync, new object[] { checksum.ToArray() }).ConfigureAwait(false);
await session.InvokeAsync(WellKnownRemoteHostServices.RemoteHostService_SynchronizePrimaryWorkspaceAsync, checksum).ConfigureAwait(false);
}
}
}
......
......@@ -26,6 +26,8 @@ internal class JsonRpcClient : IDisposable
_cancellationToken = cancellationToken;
_rpc = JsonRpc.Attach(stream, target);
_rpc.JsonSerializer.Converters.Add(AggregateJsonConverter.Instance);
_rpc.Disconnected += OnDisconnected;
}
......
......@@ -66,8 +66,8 @@ internal class JsonRpcSession : RemoteHostClient.Session
private async Task InitializeAsync()
{
// all roslyn remote service must based on ServiceHubServiceBase which implements Initialize method
await _snapshotClient.InvokeAsync(WellKnownServiceHubServices.ServiceHubServiceBase_Initialize, _currentSessionId, PinnedScope.SolutionChecksum.ToArray()).ConfigureAwait(false);
await _serviceClient.InvokeAsync(WellKnownServiceHubServices.ServiceHubServiceBase_Initialize, _currentSessionId, PinnedScope.SolutionChecksum.ToArray()).ConfigureAwait(false);
await _snapshotClient.InvokeAsync(WellKnownServiceHubServices.ServiceHubServiceBase_Initialize, _currentSessionId, PinnedScope.SolutionChecksum).ConfigureAwait(false);
await _serviceClient.InvokeAsync(WellKnownServiceHubServices.ServiceHubServiceBase_Initialize, _currentSessionId, PinnedScope.SolutionChecksum).ConfigureAwait(false);
}
public override Task InvokeAsync(string targetName, params object[] arguments)
......@@ -220,7 +220,7 @@ private async Task WriteMultipleAssetsAsync(ObjectWriter writer, byte[][] checks
var checksum = kv.Key;
var remotableData = kv.Value;
writer.WriteValue(checksum.ToArray());
checksum.WriteTo(writer);
writer.WriteString(remotableData.Kind);
await remotableData.WriteObjectToAsync(writer, _source.Token).ConfigureAwait(false);
......
......@@ -73,6 +73,7 @@ private static void RegisterWorkspaceHost(Workspace workspace, RemoteHostClient
_hostGroup = hostGroup;
_rpc = JsonRpc.Attach(stream, target: this);
_rpc.JsonSerializer.Converters.Add(AggregateJsonConverter.Instance);
// handle disconnected situation
_rpc.Disconnected += OnRpcDisconnected;
......
......@@ -77,6 +77,12 @@
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\Extensions.cs">
<Link>Shared\Extensions.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\RoslynJsonConverter.cs">
<Link>Shared\RoslynJsonConverter.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\RoslynJsonConverter.SolutionIdConverters.cs">
<Link>Shared\RoslynJsonConverter.SolutionIdConverters.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\ServerDirectStream.cs">
<Link>Shared\ServerDirectStream.cs</Link>
</Compile>
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
extern alias hub;
using System;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Text;
using Newtonsoft.Json;
using Roslyn.Test.Utilities;
using Xunit;
namespace Roslyn.VisualStudio.Next.UnitTests.Remote
{
public class JsonConverterTests
{
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestChecksum()
{
VerifyJsonSerialization(new Checksum(Guid.NewGuid().ToByteArray()));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestSolutionId()
{
VerifyJsonSerialization(SolutionId.CreateNewId("solution"));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestProjectId()
{
VerifyJsonSerialization(ProjectId.CreateNewId("project"));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestDocumentId()
{
VerifyJsonSerialization(DocumentId.CreateNewId(ProjectId.CreateNewId("project"), "document"));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestDiagnosticArguments()
{
var arguments = new hub::Microsoft.CodeAnalysis.Remote.Diagnostics.DiagnosticArguments(
reportSuppressedDiagnostics: true,
logAnalyzerExecutionTime: false,
projectId: ProjectId.CreateNewId("project"),
optionSetChecksum: Checksum.Null,
hostAnalyzerChecksums: ImmutableArray.CreateRange(new[] { new Checksum(Guid.NewGuid().ToByteArray()), new Checksum(Guid.NewGuid().ToByteArray()) }),
analyzerIds: new[] { "analyzer1", "analyzer2" });
VerifyJsonSerialization(arguments, (x, y) =>
{
if (x.ReportSuppressedDiagnostics == y.ReportSuppressedDiagnostics &&
x.LogAnalyzerExecutionTime == y.LogAnalyzerExecutionTime &&
x.ProjectId == y.ProjectId &&
x.OptionSetChecksum == y.OptionSetChecksum &&
x.HostAnalyzerChecksums.Length == y.HostAnalyzerChecksums.Length &&
x.HostAnalyzerChecksums.Except(y.HostAnalyzerChecksums).Count() == 0 &&
x.AnalyzerIds.Length == y.AnalyzerIds.Length &&
x.AnalyzerIds.Except(y.AnalyzerIds).Count() == 0)
{
return 0;
}
return 1;
});
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public void TestTextSpan()
{
VerifyJsonSerialization(new TextSpan(10, 5));
}
private static void VerifyJsonSerialization<T>(T value, Comparison<T> equality = null)
{
var serializer = new JsonSerializer();
serializer.Converters.Add(hub::Microsoft.CodeAnalysis.Remote.AggregateJsonConverter.Instance);
using (var writer = new StringWriter())
{
serializer.Serialize(writer, value);
using (var reader = new JsonTextReader(new StringReader(writer.ToString())))
{
var deserialized = serializer.Deserialize<T>(reader);
if (equality != null)
{
Assert.Equal(0, equality(value, deserialized));
return;
}
Assert.Equal(value, deserialized);
}
}
}
}
}
\ No newline at end of file
......@@ -221,7 +221,7 @@ private static async Task UpdatePrimaryWorkspace(InProcRemoteHostClient client,
{
await session.InvokeAsync(
WellKnownRemoteHostServices.RemoteHostService_SynchronizePrimaryWorkspaceAsync,
new object[] { (await solution.State.GetChecksumAsync(CancellationToken.None)).ToArray() });
await solution.State.GetChecksumAsync(CancellationToken.None));
}
}
......
......@@ -86,6 +86,7 @@
<ProjectReference Include="..\..\..\Workspaces\Remote\ServiceHub\ServiceHub.csproj">
<Project>{80fddd00-9393-47f7-8baf-7e87ce011068}</Project>
<Name>ServiceHub</Name>
<Aliases>global,hub</Aliases>
</ProjectReference>
<ProjectReference Include="..\..\..\Workspaces\VisualBasic\Portable\BasicWorkspace.vbproj">
<Project>{57ca988d-f010-4bf2-9a2e-07d6dcd2ff2c}</Project>
......@@ -190,6 +191,7 @@
<Compile Include="Mocks\TestHostServices.cs" />
<Compile Include="Mocks\InProcRemoteHostClientFactory.cs" />
<Compile Include="Mocks\TestOptionSet.cs" />
<Compile Include="Remote\JsonConverterTests.cs" />
<Compile Include="Remote\RemoteHostClientServiceFactoryTests.cs" />
<Compile Include="TestUtils.cs" />
<Compile Include="Services\SolutionServiceTests.cs" />
......
......@@ -62,7 +62,7 @@ public Checksum CreateChecksum(object value, CancellationToken cancellationToken
case WellKnownSynchronizationKinds.CompilationOptions:
case WellKnownSynchronizationKinds.ParseOptions:
case WellKnownSynchronizationKinds.ProjectReference:
return Checksum.Create(value, kind, this);
return Checksum.Create(kind, value, this);
case WellKnownSynchronizationKinds.MetadataReference:
return Checksum.Create(kind, _hostSerializationService.CreateChecksum((MetadataReference)value, cancellationToken));
......@@ -71,7 +71,7 @@ public Checksum CreateChecksum(object value, CancellationToken cancellationToken
return Checksum.Create(kind, _hostSerializationService.CreateChecksum((AnalyzerReference)value, cancellationToken));
case WellKnownSynchronizationKinds.SourceText:
return Checksum.Create(kind, new Checksum(((SourceText)value).GetChecksum()));
return Checksum.Create(kind, ((SourceText)value).GetChecksum());
default:
// object that is not part of solution is not supported since we don't know what inputs are required to
......
......@@ -7,6 +7,6 @@ namespace Microsoft.CodeAnalysis.FindSymbols
{
internal interface IRemoteSymbolFinder
{
Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, SerializableDocumentId[] documentArgs);
Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, DocumentId[] documentArgs);
}
}
\ No newline at end of file
......@@ -38,15 +38,15 @@ private class ServerCallback
public Task OnCompletedAsync() => _progress.OnCompletedAsync();
public Task ReportProgressAsync(int current, int maximum) => _progress.ReportProgressAsync(current, maximum);
public Task OnFindInDocumentStartedAsync(SerializableDocumentId documentId)
public Task OnFindInDocumentStartedAsync(DocumentId documentId)
{
var document = _solution.GetDocument(documentId.Rehydrate());
var document = _solution.GetDocument(documentId);
return _progress.OnFindInDocumentStartedAsync(document);
}
public Task OnFindInDocumentCompletedAsync(SerializableDocumentId documentId)
public Task OnFindInDocumentCompletedAsync(DocumentId documentId)
{
var document = _solution.GetDocument(documentId.Rehydrate());
var document = _solution.GetDocument(documentId);
return _progress.OnFindInDocumentCompletedAsync(document);
}
......
......@@ -75,7 +75,7 @@ public static partial class SymbolFinder
await session.InvokeAsync(
nameof(IRemoteSymbolFinder.FindReferencesAsync),
SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId),
documents?.Select(SerializableDocumentId.Dehydrate).ToArray()).ConfigureAwait(false);
documents?.Select(d => d.Id).ToArray()).ConfigureAwait(false);
}
}
}
......
......@@ -12,88 +12,12 @@
namespace Microsoft.CodeAnalysis.Remote
{
#region Common Arguments
/// <summary>
/// Arguments to pass from client to server when performing operations
/// </summary>
internal class SerializableProjectId : IEquatable<SerializableProjectId>
{
public Guid Id;
public string DebugName;
public override int GetHashCode()
=> Hash.Combine(Id.GetHashCode(), DebugName.GetHashCode());
public override bool Equals(object obj)
=> Equals(obj as SerializableProjectId);
public bool Equals(SerializableProjectId obj)
=> obj != null && Id.Equals(obj.Id) && DebugName.Equals(obj.DebugName);
public static SerializableProjectId Dehydrate(ProjectId id)
{
return new SerializableProjectId { Id = id.Id, DebugName = id.DebugName };
}
public ProjectId Rehydrate()
{
return ProjectId.CreateFromSerialized(Id, DebugName);
}
}
internal class SerializableDocumentId
{
public SerializableProjectId ProjectId;
public Guid Id;
public string DebugName;
public static SerializableDocumentId Dehydrate(Document document)
{
return Dehydrate(document.Id);
}
public static SerializableDocumentId Dehydrate(DocumentId id)
{
return new SerializableDocumentId
{
ProjectId = SerializableProjectId.Dehydrate(id.ProjectId),
Id = id.Id,
DebugName = id.DebugName
};
}
public DocumentId Rehydrate()
{
return DocumentId.CreateFromSerialized(
ProjectId.Rehydrate(), Id, DebugName);
}
}
internal class SerializableTextSpan
{
public int Start;
public int Length;
public static SerializableTextSpan Dehydrate(TextSpan textSpan)
{
return new SerializableTextSpan { Start = textSpan.Start, Length = textSpan.Length };
}
public TextSpan Rehydrate()
{
return new TextSpan(Start, Length);
}
}
#endregion
#region FindReferences
internal class SerializableSymbolAndProjectId : IEquatable<SerializableSymbolAndProjectId>
{
public string SymbolKeyData;
public SerializableProjectId ProjectId;
public ProjectId ProjectId;
public override int GetHashCode()
=> Hash.Combine(SymbolKeyData, ProjectId.GetHashCode());
......@@ -118,14 +42,14 @@ public bool Equals(SerializableSymbolAndProjectId other)
return new SerializableSymbolAndProjectId
{
SymbolKeyData = symbolAndProjectId.Symbol.GetSymbolKey().ToString(),
ProjectId = SerializableProjectId.Dehydrate(symbolAndProjectId.ProjectId)
ProjectId = symbolAndProjectId.ProjectId
};
}
public async Task<SymbolAndProjectId> RehydrateAsync(
Solution solution, CancellationToken cancellationToken)
{
var projectId = ProjectId.Rehydrate();
var projectId = ProjectId;
var project = solution.GetProject(projectId);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbol = SymbolKey.Resolve(SymbolKeyData, compilation, cancellationToken: cancellationToken).GetAnySymbol();
......@@ -136,11 +60,11 @@ public bool Equals(SerializableSymbolAndProjectId other)
internal class SerializableReferenceLocation
{
public SerializableDocumentId Document { get; set; }
public DocumentId Document { get; set; }
public SerializableSymbolAndProjectId Alias { get; set; }
public SerializableTextSpan Location { get; set; }
public TextSpan Location { get; set; }
public bool IsImplicit { get; set; }
......@@ -153,9 +77,9 @@ internal class SerializableReferenceLocation
{
return new SerializableReferenceLocation
{
Document = SerializableDocumentId.Dehydrate(referenceLocation.Document),
Document = referenceLocation.Document.Id,
Alias = SerializableSymbolAndProjectId.Dehydrate(referenceLocation.Alias, referenceLocation.Document),
Location = SerializableTextSpan.Dehydrate(referenceLocation.Location.SourceSpan),
Location = referenceLocation.Location.SourceSpan,
IsImplicit = referenceLocation.IsImplicit,
IsWrittenTo = referenceLocation.IsWrittenTo,
CandidateReason = referenceLocation.CandidateReason
......@@ -165,13 +89,13 @@ internal class SerializableReferenceLocation
public async Task<ReferenceLocation> RehydrateAsync(
Solution solution, CancellationToken cancellationToken)
{
var document = solution.GetDocument(this.Document.Rehydrate());
var document = solution.GetDocument(this.Document);
var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
var aliasSymbol = await RehydrateAliasAsync(solution, cancellationToken).ConfigureAwait(false);
return new ReferenceLocation(
document,
aliasSymbol,
CodeAnalysis.Location.Create(syntaxTree, Location.Rehydrate()),
CodeAnalysis.Location.Create(syntaxTree, Location),
isImplicit: IsImplicit,
isWrittenTo: IsWrittenTo,
candidateReason: CandidateReason);
......
......@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Roslyn.Utilities;
......@@ -14,30 +13,18 @@ namespace Microsoft.CodeAnalysis
/// </summary>
internal sealed partial class Checksum : IObjectWritable, IEquatable<Checksum>
{
public static readonly Checksum Null = new Checksum(ImmutableArray<byte>.Empty);
public static readonly Checksum Null = new Checksum(Array.Empty<byte>());
private readonly ImmutableArray<byte> _checkSum;
private readonly byte[] _checkSum;
private int _lazyHash;
public Checksum(byte[] checksum) :
this(ImmutableArray.Create(checksum))
{
}
public Checksum(ImmutableArray<byte> checksum)
public Checksum(byte[] checksum)
{
// 0 means it is not initialized
_lazyHash = 0;
_checkSum = checksum;
}
public byte[] ToArray()
{
// TODO: think a way to make this better
return _checkSum.ToArray();
}
public bool Equals(Checksum other)
{
if (other == null)
......@@ -78,7 +65,7 @@ public override int GetHashCode()
public override string ToString()
{
return Convert.ToBase64String(ToArray());
return Convert.ToBase64String(_checkSum);
}
private int CalculateHashCode()
......@@ -107,25 +94,12 @@ private int CalculateHashCode()
public void WriteTo(ObjectWriter writer)
{
writer.WriteInt32(_checkSum.Length);
for (var i = 0; i < _checkSum.Length; i++)
{
writer.WriteByte(_checkSum[i]);
}
writer.WriteValue(_checkSum);
}
public static Checksum ReadFrom(ObjectReader reader)
{
var length = reader.ReadInt32();
var builder = ImmutableArray.CreateBuilder<byte>(length);
for (var i = 0; i < length; i++)
{
builder.Add(reader.ReadByte());
}
return new Checksum(builder.MoveToImmutable());
return new Checksum((byte[])reader.ReadValue());
}
public static string GetChecksumLogInfo(Checksum checksum)
......
// 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.Immutable;
using System.IO;
using System.Threading;
using Roslyn.Utilities;
using System.Security.Cryptography;
using System.Threading;
using Microsoft.CodeAnalysis.Serialization;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
{
......@@ -24,20 +24,19 @@ public static Checksum Create(Stream stream)
}
}
public static Checksum Create(string kind, Checksum checksum)
public static Checksum Create(string kind, IObjectWritable @object)
{
using (var stream = SerializableBytes.CreateWritableStream())
using (var writer = new StreamObjectWriter(stream))
using (var objectWriter = new StreamObjectWriter(stream))
{
writer.WriteString(kind);
checksum.WriteTo(writer);
objectWriter.WriteString(kind);
@object.WriteTo(objectWriter);
return Create(stream);
}
}
public static Checksum Create<TChecksums>(string kind, TChecksums checksums)
where TChecksums : IEnumerable<Checksum>
public static Checksum Create(string kind, IEnumerable<Checksum> checksums)
{
using (var stream = SerializableBytes.CreateWritableStream())
using (var writer = new StreamObjectWriter(stream))
......@@ -53,25 +52,29 @@ public static Checksum Create<TChecksums>(string kind, TChecksums checksums)
}
}
public static Checksum Create<T>(T value, string kind, Serializer serializer)
public static Checksum Create(string kind, ImmutableArray<byte> bytes)
{
using (var stream = SerializableBytes.CreateWritableStream())
using (var objectWriter = new StreamObjectWriter(stream))
using (var writer = new StreamObjectWriter(stream))
{
objectWriter.WriteString(kind);
serializer.Serialize(value, objectWriter, CancellationToken.None);
writer.WriteString(kind);
for (var i = 0; i < bytes.Length; i++)
{
writer.WriteByte(bytes[i]);
}
return Create(stream);
}
}
public static Checksum Create(IObjectWritable @object, string kind)
public static Checksum Create<T>(string kind, T value, Serializer serializer)
{
using (var stream = SerializableBytes.CreateWritableStream())
using (var objectWriter = new StreamObjectWriter(stream))
{
objectWriter.WriteString(kind);
@object.WriteTo(objectWriter);
serializer.Serialize(value, objectWriter, CancellationToken.None);
return Create(stream);
}
}
......
......@@ -234,7 +234,7 @@ Checksum IChecksummedObject.Checksum
{
if (_lazyChecksum == null)
{
_lazyChecksum = Checksum.Create(this, nameof(DocumentAttributes));
_lazyChecksum = Checksum.Create(nameof(DocumentAttributes), this);
}
return _lazyChecksum;
......
......@@ -474,7 +474,7 @@ Checksum IChecksummedObject.Checksum
{
if (_lazyChecksum == null)
{
_lazyChecksum = Checksum.Create(this, nameof(ProjectAttributes));
_lazyChecksum = Checksum.Create(nameof(ProjectAttributes), this);
}
return _lazyChecksum;
......
......@@ -138,7 +138,7 @@ Checksum IChecksummedObject.Checksum
{
if (_lazyChecksum == null)
{
_lazyChecksum = Checksum.Create(this, nameof(SolutionAttributes));
_lazyChecksum = Checksum.Create(nameof(SolutionAttributes), this);
}
return _lazyChecksum;
......
......@@ -13,6 +13,10 @@
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup Label="Project References">
<ProjectReference Include="..\..\..\Compilers\Core\Portable\CodeAnalysis.csproj">
<Project>{1ee8cad3-55f9-4d91-96b2-084641da9a6c}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\Core\Portable\Workspaces.csproj">
<Project>{5F8D2414-064A-4B3A-9B42-8E2A04246BE5}</Project>
<Name>Workspaces</Name>
......@@ -36,6 +40,12 @@
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Compile Include="..\ServiceHub\Shared\RoslynJsonConverter.cs">
<Link>Shared\RoslynJsonConverter.cs</Link>
</Compile>
<Compile Include="..\ServiceHub\Shared\RoslynJsonConverter.SolutionIdConverters.cs">
<Link>Shared\RoslynJsonConverter.SolutionIdConverters.cs</Link>
</Compile>
<Compile Include="..\ServiceHub\Shared\ServiceHubServiceBase.cs">
<Link>Shared\ServiceHubServiceBase.cs</Link>
</Compile>
......
{
"dependencies": {
"StreamJsonRpc": "0.12.32-alpha-g90be50f449"
"StreamJsonRpc": "1.0.2-rc"
},
"frameworks": {
"net46": {}
......
// 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.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Execution;
namespace Microsoft.CodeAnalysis.Remote.Diagnostics
{
......@@ -15,10 +12,9 @@ internal class DiagnosticArguments
{
public bool ReportSuppressedDiagnostics;
public bool LogAnalyzerExecutionTime;
public Guid ProjectIdGuid;
public string ProjectIdDebugName;
public byte[] OptionSetChecksumBytes;
public byte[][] HostAnalyzerChecksumsByteArray;
public ProjectId ProjectId;
public Checksum OptionSetChecksum;
public Checksum[] HostAnalyzerChecksums;
public string[] AnalyzerIds;
public DiagnosticArguments()
......@@ -29,23 +25,18 @@ public DiagnosticArguments()
bool reportSuppressedDiagnostics,
bool logAnalyzerExecutionTime,
ProjectId projectId,
byte[] optionSetChecksum,
ImmutableArray<byte[]> hostAnalyzerChecksums,
Checksum optionSetChecksum,
ImmutableArray<Checksum> hostAnalyzerChecksums,
string[] analyzerIds)
{
ReportSuppressedDiagnostics = reportSuppressedDiagnostics;
LogAnalyzerExecutionTime = logAnalyzerExecutionTime;
ProjectIdGuid = projectId.Id;
ProjectIdDebugName = projectId.DebugName;
ProjectId = projectId;
OptionSetChecksumBytes = optionSetChecksum;
HostAnalyzerChecksumsByteArray = hostAnalyzerChecksums.ToArray();
OptionSetChecksum = optionSetChecksum;
HostAnalyzerChecksums = hostAnalyzerChecksums.ToArray();
AnalyzerIds = analyzerIds;
}
public ProjectId GetProjectId() => ProjectId.CreateFromSerialized(ProjectIdGuid, ProjectIdDebugName);
public IEnumerable<Checksum> GetHostAnalyzerChecksums() => HostAnalyzerChecksumsByteArray.Select(b => new Checksum(b));
public Checksum GetOptionSetChecksum() => new Checksum(OptionSetChecksumBytes);
}
}
\ No newline at end of file
......@@ -69,6 +69,8 @@
<Compile Include="Shared\ServiceHubServiceBase.cs" />
<Compile Include="Services\SnapshotService.cs" />
<Compile Include="Shared\Extensions.cs" />
<Compile Include="Shared\RoslynJsonConverter.cs" />
<Compile Include="Shared\RoslynJsonConverter.SolutionIdConverters.cs" />
<Compile Include="Shared\ServerDirectStream.cs" />
<Compile Include="Shared\ClientDirectStream.cs" />
</ItemGroup>
......
......@@ -26,17 +26,17 @@ internal partial class CodeAnalysisService
/// </summary>
public async Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, string streamName)
{
using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_CalculateDiagnosticsAsync, arguments.ProjectIdDebugName, CancellationToken))
using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_CalculateDiagnosticsAsync, arguments.ProjectId.DebugName, CancellationToken))
{
try
{
var optionSet = await RoslynServices.AssetService.GetAssetAsync<OptionSet>(arguments.GetOptionSetChecksum(), CancellationToken).ConfigureAwait(false);
var optionSet = await RoslynServices.AssetService.GetAssetAsync<OptionSet>(arguments.OptionSetChecksum, CancellationToken).ConfigureAwait(false);
// entry point for diagnostic service
var solution = await GetSolutionWithSpecificOptionsAsync(optionSet).ConfigureAwait(false);
var projectId = arguments.GetProjectId();
var analyzers = await GetHostAnalyzerReferences(arguments.GetHostAnalyzerChecksums()).ConfigureAwait(false);
var projectId = arguments.ProjectId;
var analyzers = await GetHostAnalyzerReferences(arguments.HostAnalyzerChecksums).ConfigureAwait(false);
var result = await (new DiagnosticComputer(solution.GetProject(projectId))).GetDiagnosticsAsync(
analyzers, arguments.AnalyzerIds, arguments.ReportSuppressedDiagnostics, arguments.LogAnalyzerExecutionTime, CancellationToken).ConfigureAwait(false);
......
......@@ -10,14 +10,13 @@ namespace Microsoft.CodeAnalysis.Remote
// root level service for all Roslyn services
internal partial class CodeAnalysisService : IRemoteSymbolFinder
{
public async Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, SerializableDocumentId[] documentArgs)
public async Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, DocumentId[] documentArgs)
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var symbolAndProjectId = await symbolAndProjectIdArg.RehydrateAsync(
solution, CancellationToken).ConfigureAwait(false);
var documents = documentArgs?.Select(a => a.Rehydrate())
.Select(solution.GetDocument)
var documents = documentArgs?.Select(solution.GetDocument)
.ToImmutableHashSet();
var progressCallback = new ProgressCallback(this);
......@@ -44,12 +43,10 @@ public Task ReportProgressAsync(int current, int maximum)
=> _service.Rpc.InvokeAsync(nameof(ReportProgressAsync), current, maximum);
public Task OnFindInDocumentStartedAsync(Document document)
=> _service.Rpc.InvokeAsync(nameof(OnFindInDocumentStartedAsync),
SerializableDocumentId.Dehydrate(document));
=> _service.Rpc.InvokeAsync(nameof(OnFindInDocumentStartedAsync), document.Id);
public Task OnFindInDocumentCompletedAsync(Document document)
=> _service.Rpc.InvokeAsync(nameof(OnFindInDocumentCompletedAsync),
SerializableDocumentId.Dehydrate(document));
=> _service.Rpc.InvokeAsync(nameof(OnFindInDocumentCompletedAsync), document.Id);
public Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
=> _service.Rpc.InvokeAsync(nameof(OnDefinitionFoundAsync),
......
......@@ -10,11 +10,11 @@ namespace Microsoft.CodeAnalysis.Remote
internal partial class CodeAnalysisService : IRemoteNavigateToSearchService
{
public async Task<SerializableNavigateToSearchResult[]> SearchDocumentAsync(
SerializableDocumentId documentId, string searchPattern)
DocumentId documentId, string searchPattern)
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var project = solution.GetDocument(documentId.Rehydrate());
var project = solution.GetDocument(documentId);
var result = await AbstractNavigateToSearchService.SearchDocumentInCurrentProcessAsync(
project, searchPattern, CancellationToken).ConfigureAwait(false);
......@@ -22,11 +22,11 @@ internal partial class CodeAnalysisService : IRemoteNavigateToSearchService
}
public async Task<SerializableNavigateToSearchResult[]> SearchProjectAsync(
SerializableProjectId projectId, string searchPattern)
ProjectId projectId, string searchPattern)
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var project = solution.GetProject(projectId.Rehydrate());
var project = solution.GetProject(projectId);
var result = await AbstractNavigateToSearchService.SearchProjectInCurrentProcessAsync(
project, searchPattern, CancellationToken).ConfigureAwait(false);
......
......@@ -46,7 +46,7 @@ private class JsonRpcAssetSource : AssetSource
using (RoslynLogger.LogBlock(FunctionId.SnapshotService_RequestAssetAsync, GetRequestLogInfo, sessionId, checksums, mergedCancellationToken.Token))
{
return await _owner.Rpc.InvokeAsync(WellKnownServiceHubServices.AssetService_RequestAssetAsync,
new object[] { sessionId, checksums.Select(c => c.ToArray()).ToArray() },
new object[] { sessionId, checksums.ToArray() },
(s, c) => ReadAssets(s, sessionId, checksums, c), mergedCancellationToken.Token).ConfigureAwait(false);
}
}
......
// 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 Newtonsoft.Json;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Remote
{
internal partial class AggregateJsonConverter : JsonConverter
{
private abstract class WorkspaceIdJsonConverter : BaseJsonConverter
{
protected (Guid, string) ReadFromJsonObject(JsonReader reader)
{
Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject);
var (id, debugName) = ReadIdAndName(reader);
Contract.ThrowIfFalse(reader.Read());
Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject);
return (id, debugName);
}
protected void WriteToJsonObject(JsonWriter writer, Guid id, string debugName)
{
writer.WriteStartObject();
WriteIdAndName(writer, id, debugName);
writer.WriteEndObject();
}
protected (Guid, string) ReadIdAndName(JsonReader reader)
{
var id = new Guid(ReadProperty<string>(reader));
var debugName = ReadProperty<string>(reader);
return (id, debugName);
}
protected static void WriteIdAndName(JsonWriter writer, Guid id, string debugName)
{
writer.WritePropertyName(nameof(id));
writer.WriteValue(id);
writer.WritePropertyName(nameof(debugName));
writer.WriteValue(debugName);
}
}
private class SolutionIdJsonConverter : WorkspaceIdJsonConverter
{
public override bool CanConvert(Type objectType) => typeof(SolutionId) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var (id, debugName) = ReadFromJsonObject(reader);
return SolutionId.CreateFromSerialized(id, debugName);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var solutionId = (SolutionId)value;
WriteToJsonObject(writer, solutionId.Id, solutionId.DebugName);
}
}
private class ProjectIdJsonConverter : WorkspaceIdJsonConverter
{
public override bool CanConvert(Type objectType) => typeof(ProjectId) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var (id, debugName) = ReadFromJsonObject(reader);
return ProjectId.CreateFromSerialized(id, debugName);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var projectId = (ProjectId)value;
WriteToJsonObject(writer, projectId.Id, projectId.DebugName);
}
}
private class DocumentIdJsonConverter : WorkspaceIdJsonConverter
{
public override bool CanConvert(Type objectType) => typeof(DocumentId) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject);
var projectId = ReadProperty<ProjectId>(serializer, reader);
var (id, debugName) = ReadIdAndName(reader);
Contract.ThrowIfFalse(reader.Read());
Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject);
return DocumentId.CreateFromSerialized(projectId, id, debugName);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var documentId = (DocumentId)value;
writer.WriteStartObject();
writer.WritePropertyName("projectId");
serializer.Serialize(writer, documentId.ProjectId);
WriteIdAndName(writer, documentId.Id, documentId.DebugName);
writer.WriteEndObject();
}
}
}
}
// 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.Immutable;
using Microsoft.CodeAnalysis.Text;
using Newtonsoft.Json;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Remote
{
internal partial class AggregateJsonConverter : JsonConverter
{
public static readonly AggregateJsonConverter Instance = new AggregateJsonConverter();
private readonly ImmutableDictionary<Type, JsonConverter> _map;
private AggregateJsonConverter()
{
_map = CreateConverterMap();
}
public override bool CanConvert(Type objectType)
{
return _map.ContainsKey(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return _map[objectType].ReadJson(reader, objectType, existingValue, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
_map[value.GetType()].WriteJson(writer, value, serializer);
}
private ImmutableDictionary<Type, JsonConverter> CreateConverterMap()
{
var builder = ImmutableDictionary.CreateBuilder<Type, JsonConverter>();
builder.Add(typeof(Checksum), new ChecksumJsonConverter());
builder.Add(typeof(SolutionId), new SolutionIdJsonConverter());
builder.Add(typeof(ProjectId), new ProjectIdJsonConverter());
builder.Add(typeof(DocumentId), new DocumentIdJsonConverter());
builder.Add(typeof(TextSpan), new TextSpanJsonConverter());
return builder.ToImmutable();
}
private abstract class BaseJsonConverter : JsonConverter
{
protected static T ReadProperty<T>(JsonSerializer serializer, JsonReader reader)
{
// read property
Contract.ThrowIfFalse(reader.Read());
Contract.ThrowIfFalse(reader.TokenType == JsonToken.PropertyName);
Contract.ThrowIfFalse(reader.Read());
return serializer.Deserialize<T>(reader);
}
protected static T ReadProperty<T>(JsonReader reader)
{
// read property
Contract.ThrowIfFalse(reader.Read());
Contract.ThrowIfFalse(reader.TokenType == JsonToken.PropertyName);
Contract.ThrowIfFalse(reader.Read());
return (T)reader.Value;
}
}
private class TextSpanJsonConverter : BaseJsonConverter
{
public override bool CanConvert(Type objectType) => typeof(TextSpan) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Contract.ThrowIfFalse(reader.TokenType == JsonToken.StartObject);
// all integer is long
var start = ReadProperty<long>(reader);
var length = ReadProperty<long>(reader);
Contract.ThrowIfFalse(reader.Read());
Contract.ThrowIfFalse(reader.TokenType == JsonToken.EndObject);
return new TextSpan((int)start, (int)length);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var span = (TextSpan)value;
writer.WriteStartObject();
writer.WritePropertyName("start");
writer.WriteValue(span.Start);
writer.WritePropertyName("length");
writer.WriteValue(span.Length);
writer.WriteEndObject();
}
}
private class ChecksumJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => typeof(Checksum) == objectType;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
new Checksum(Convert.FromBase64String((string)reader.Value));
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
writer.WriteValue(value.ToString());
}
}
}
......@@ -43,6 +43,8 @@ protected ServiceHubServiceBase(Stream stream, IServiceProvider serviceProvider)
CancellationToken = _cancellationTokenSource.Token;
Rpc = JsonRpc.Attach(stream, this);
Rpc.JsonSerializer.Converters.Add(AggregateJsonConverter.Instance);
Rpc.Disconnected += OnRpcDisconnected;
}
......
{
"dependencies": {
"StreamJsonRpc": "0.12.32-alpha-g90be50f449"
},
"frameworks": {
"net46": { }
}
"dependencies": {
"StreamJsonRpc": "1.0.2-rc"
},
"frameworks": {
"net46": { }
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册