提交 a51c7974 编写于 作者: C CyrusNajmabadi

Flesh out the host side of remote FAR.

上级 819dabde
......@@ -11,6 +11,5 @@ internal class WellKnownRemoteHostServices
public const string RemoteHostService_PersistentStorageService_RegisterPrimarySolutionId = "PersistentStorageService_RegisterPrimarySolutionId";
public const string RemoteHostService_PersistentStorageService_UnregisterPrimarySolutionId = "PersistentStorageService_UnregisterPrimarySolutionId";
public const string RemoteHostService_PersistentStorageService_UpdateSolutionIdStorageLocation = "PersistentStorageService_UpdateSolutionIdStorageLocation";
}
}
\ No newline at end of file
......@@ -11,14 +11,18 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Extensions
{
internal static class RemoteHostClientExtensions
{
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(this RemoteHostClient client, Solution solution, CancellationToken cancellationToken)
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(
this RemoteHostClient client, Solution solution, CancellationToken cancellationToken)
{
return CreateCodeAnalysisServiceSessionAsync(client, solution, callbackTarget: null, cancellationToken: cancellationToken);
return CreateCodeAnalysisServiceSessionAsync(
client, solution, callbackTarget: null, cancellationToken: cancellationToken);
}
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(this RemoteHostClient client, Solution solution, object callbackTarget, CancellationToken cancellationToken)
public static Task<Session> CreateCodeAnalysisServiceSessionAsync(
this RemoteHostClient client, Solution solution, object callbackTarget, CancellationToken cancellationToken)
{
return client.CreateServiceSessionAsync(WellKnownServiceHubServices.CodeAnalysisService, solution, callbackTarget, cancellationToken);
return client.CreateServiceSessionAsync(
WellKnownServiceHubServices.CodeAnalysisService, solution, callbackTarget, cancellationToken);
}
}
}
// 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.Composition;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.VisualStudio.LanguageServices.Remote;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Remote.FindReferences;
using Microsoft.VisualStudio.LanguageServices.Implementation.Extensions;
using Microsoft.VisualStudio.LanguageServices.Remote;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.FindSymbols
{
[ExportWorkspaceService(typeof(ISymbolFinderEngineService), ServiceLayer.Host), Shared]
internal class VisualStudioSymbolFinderEngineService : ISymbolFinderEngineService
{
public Task FindReferencesAsync(
public async Task FindReferencesAsync(
SymbolAndProjectId symbolAndProjectId, Solution solution,
IStreamingFindReferencesProgress progress,
IImmutableSet<Document> documents, CancellationToken cancellationToken)
{
return DefaultSymbolFinderEngineService.FindReferencesInCurrentProcessAsync(
symbolAndProjectId, solution, progress, documents, cancellationToken);
using (Logger.LogBlock(FunctionId.FindReference, cancellationToken))
{
if (symbolAndProjectId.ProjectId == null)
{
// This is a call through our old public API. We don't have the necessary
// data to effectively run the call out of proc.
await DefaultSymbolFinderEngineService.FindReferencesInCurrentProcessAsync(
symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
}
else
{
await FindReferencesInServiceProcessAsync(
symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
}
}
#if false
var symbol = symbolAndProjectId.Symbol;
var symbolKeyData = symbol.GetSymbolKey().ToString();
var progressCallback = new ProgressCallback(progress);
#endif
}
private async Task FindReferencesInServiceProcessAsync(
SymbolAndProjectId symbolAndProjectId,
Solution solution,
IStreamingFindReferencesProgress progress,
IImmutableSet<Document> documents,
CancellationToken cancellationToken)
{
var clientService = solution.Workspace.Services.GetService<IRemoteHostClientService>();
var client = await clientService.GetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false);
using (var session = await client.CreateCodeAnalysisServiceSessionAsync(solution, progressCallback, cancellationToken).ConfigureAwait(false))
if (client == null)
{
// await session.InvokeAsync()
await DefaultSymbolFinderEngineService.FindReferencesInCurrentProcessAsync(
symbolAndProjectId, solution, progress, documents, cancellationToken).ConfigureAwait(false);
return;
}
return null;
#endif
var serverCallback = new ServerCallback(solution, progress, cancellationToken);
using (var session = await client.CreateCodeAnalysisServiceSessionAsync(
solution, serverCallback, cancellationToken).ConfigureAwait(false))
{
await session.InvokeAsync(
WellKnownServiceHubServices.CodeAnalysisService_FindReferencesAsync,
SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId),
documents.Select(SerializableDocumentId.Dehydrate).ToArray()).ConfigureAwait(false);
}
}
#if false
private class ProgressCallback
private class ServerCallback
{
private readonly Solution _solution;
private readonly IStreamingFindReferencesProgress _progress;
private readonly CancellationToken _cancellationToken;
public ProgressCallback(
public ServerCallback(
Solution solution,
IStreamingFindReferencesProgress progress)
IStreamingFindReferencesProgress progress,
CancellationToken cancellationToken)
{
_solution = solution;
_progress = progress;
_cancellationToken = cancellationToken;
}
public Task OnStarted() => _progress.OnStartedAsync();
public Task OnCompletedAsync() => _progress.OnCompletedAsync();
public Task ReportProgressAsync(int current, int maximum) => _progress.ReportProgressAsync(current, maximum);
public void OnFindInDocumentStarted(
Guid projectGuid, string projectDebugName,
Guid documentGuid, string documentDebugName)
public Task OnFindInDocumentStartedAsync(SerializableDocumentId documentId)
{
var document = GetDocument(projectGuid, projectDebugName, documentGuid, documentDebugName);
_progress.OnFindInDocumentStarted(document);
var document = _solution.GetDocument(documentId.Rehydrate());
return _progress.OnFindInDocumentStartedAsync(document);
}
public void OnFindInDocumentCompleted(
Guid projectGuid, string projectDebugName,
Guid documentGuid, string documentDebugName)
public Task OnFindInDocumentCompletedAsync(SerializableDocumentId documentId)
{
var document = GetDocument(projectGuid, projectDebugName, documentGuid, documentDebugName);
_progress.OnFindInDocumentCompleted(document);
var document = _solution.GetDocument(documentId.Rehydrate());
return _progress.OnFindInDocumentCompletedAsync(document);
}
private Document GetDocument(Guid projectGuid, string projectDebugName, Guid documentGuid, string documentDebugName)
public async Task OnDefinitionFoundAsync(SerializableSymbolAndProjectId argument)
{
var projectId = ProjectId.CreateFromSerialized(projectGuid, projectDebugName);
var documentId = DocumentId.CreateFromSerialized(projectId, documentGuid, documentDebugName);
var document = _solution.GetDocument(documentId);
return document;
var symbolAndProjectId = await argument.RehydrateAsync(
_solution, _cancellationToken).ConfigureAwait(false);
await _progress.OnDefinitionFoundAsync(symbolAndProjectId).ConfigureAwait(false);
}
public void OnDefinitionFound(string symbolKeyData)
public async Task OnReferenceFoundAsync(
SerializableSymbolAndProjectId definition, SerializableReferenceLocation reference)
{
var symbolKey = SymbolKey.Resolve(symbolKey, )
var symbolAndProjectId = await definition.RehydrateAsync(
_solution, _cancellationToken).ConfigureAwait(false);
var referenceLocation = await reference.RehydrateAsync(
_solution, _cancellationToken).ConfigureAwait(false);
await _progress.OnReferenceFoundAsync(symbolAndProjectId, referenceLocation).ConfigureAwait(false);
}
public void OnReferenceFound(ISymbol symbol, ReferenceLocation location);
}
#endif
}
}
\ No newline at end of file
......@@ -83,9 +83,15 @@
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Diagnostics\DiagnosticResultSerializer.cs">
<Link>Diagnostics\DiagnosticResultSerializer.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\FindReferences\FindReferencesArgument.cs">
<Link>FindSymbols\FindReferencesArgument.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\ClientDirectStream.cs">
<Link>Shared\ClientDirectStream.cs</Link>
</Compile>
<Compile Include="..\..\Workspaces\Remote\ServiceHub\Shared\ClientDirectStream.cs">
<Link>Shared\ClientDirectStream.cs</Link>
</Compile>
<Compile Include="..\..\..\Workspaces\Remote\ServiceHub\Shared\Extensions.cs">
<Link>Shared\Extensions.cs</Link>
</Compile>
......@@ -134,5 +140,8 @@
<InternalsVisibleToTest Include="Roslyn.VisualStudio.Test.Utilities.Next" />
<InternalsVisibleToTest Include="Roslyn.VisualStudio.Next.UnitTests" />
</ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</Project>
\ No newline at end of file
// 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.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Remote.FindReferences
{
/// <summary>
/// Arguments to pass from client to server when performing the FindReferences
/// call.
/// </summary>
// internal class FindReferencesArgument
// {
//#if false
// SymbolAndProjectId symbolAndProjectId,
// Solution solution,
// IStreamingFindReferencesProgress progress,
// IImmutableSet<Document> documents,
// CancellationToken cancellationToken
//#endif
// public SerializableSymbolAndProjectId SymbolAndProjectId;
// public DocumentIdArgument[] Documents;
// public static FindReferencesArgument Dehydrate(
// SymbolAndProjectId symbolAndProjectId, IImmutableSet<Document> documents)
// {
// return new FindReferencesArgument
// {
// SymbolAndProjectId = SerializableSymbolAndProjectId.Dehydrate(symbolAndProjectId),
// Documents = documents.Select(d => DocumentIdArgument.Dehydrate(d.Id)).ToArray()
// };
// }
// }
internal class SerializableProjectId
{
public Guid Id;
public string 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 SerializableSymbolAndProjectId
{
public string SymbolKeyData;
public SerializableProjectId ProjectId;
public static SerializableSymbolAndProjectId Dehydrate(
IAliasSymbol alias, Document document)
{
return alias == null
? null
: Dehydrate(new SymbolAndProjectId(alias, document.Project.Id));
}
public static SerializableSymbolAndProjectId Dehydrate(
SymbolAndProjectId symbolAndProjectId)
{
return new SerializableSymbolAndProjectId
{
SymbolKeyData = symbolAndProjectId.Symbol.GetSymbolKey().ToString(),
ProjectId = SerializableProjectId.Dehydrate(symbolAndProjectId.ProjectId)
};
}
public async Task<SymbolAndProjectId> RehydrateAsync(
Solution solution, CancellationToken cancellationToken)
{
var projectId = ProjectId.Rehydrate();
var project = solution.GetProject(projectId);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbol = SymbolKey.Resolve(SymbolKeyData, compilation, cancellationToken: cancellationToken).GetAnySymbol();
Debug.Assert(symbol != null, "We should always be able to resolve a symbol back on the host side.");
return new SymbolAndProjectId(symbol, projectId);
}
}
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);
}
}
internal class SerializableReferenceLocation
{
public SerializableDocumentId Document { get; set; }
public SerializableSymbolAndProjectId Alias { get; set; }
public SerializableTextSpan Location { get; set; }
public bool IsImplicit { get; set; }
internal bool IsWrittenTo { get; set; }
public CandidateReason CandidateReason { get; set; }
public static SerializableReferenceLocation Dehydrate(
ReferenceLocation referenceLocation)
{
return new SerializableReferenceLocation
{
Document = SerializableDocumentId.Dehydrate(referenceLocation.Document),
Alias = SerializableSymbolAndProjectId.Dehydrate(referenceLocation.Alias, referenceLocation.Document),
Location = SerializableTextSpan.Dehydrate(referenceLocation.Location.SourceSpan),
IsImplicit = referenceLocation.IsImplicit,
IsWrittenTo = referenceLocation.IsWrittenTo,
CandidateReason = referenceLocation.CandidateReason
};
}
public async Task<ReferenceLocation> RehydrateAsync(
Solution solution, CancellationToken cancellationToken)
{
var document = solution.GetDocument(this.Document.Rehydrate());
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()),
isImplicit: IsImplicit,
isWrittenTo: IsWrittenTo,
candidateReason: CandidateReason);
}
private async Task<IAliasSymbol> RehydrateAliasAsync(
Solution solution, CancellationToken cancellationToken)
{
if (Alias == null)
{
return null;
}
var symbolAndProjectId = await Alias.RehydrateAsync(solution, cancellationToken).ConfigureAwait(false);
return symbolAndProjectId.Symbol as IAliasSymbol;
}
}
}
\ No newline at end of file
......@@ -49,13 +49,14 @@
</ItemGroup>
<ItemGroup>
<None Include="project.json" />
<Compile Include="CodeLens\CodeLensArguments.cs" />
<Compile Include="Services\CodeAnalysisService_CodeLens.cs" />
<Compile Include="Services\SnapshotService.JsonRpcAssetSource.cs" />
<PublicAPI Include="PublicAPI.Shipped.txt" />
<PublicAPI Include="PublicAPI.Unshipped.txt" />
</ItemGroup>
<ItemGroup>
<Compile Include="CodeLens\CodeLensArguments.cs" />
<Compile Include="Services\CodeAnalysisService_CodeLens.cs" />
<Compile Include="FindReferences\FindReferencesArgument.cs" />
<Compile Include="Services\SnapshotService.JsonRpcAssetSource.cs" />
<Compile Include="Diagnostics\DiagnosticResultSerializer.cs" />
<Compile Include="Diagnostics\DiagnosticArguments.cs" />
<Compile Include="Services\CodeAnalysisService.cs" />
......
......@@ -9,11 +9,16 @@ internal static class WellKnownServiceHubServices
public const string CodeAnalysisService = "codeAnalysisService";
public const string CodeAnalysisService_CalculateDiagnosticsAsync = "CalculateDiagnosticsAsync";
// CodeLens methods.
public const string CodeAnalysisService_GetReferenceCountAsync = "GetReferenceCountAsync";
public const string CodeAnalysisService_FindReferenceLocationsAsync = "FindReferenceLocationsAsync";
public const string CodeAnalysisService_FindReferenceMethodsAsync = "FindReferenceMethodsAsync";
public const string CodeAnalysisService_GetFullyQualifiedName = "GetFullyQualifiedName";
// FindReferences methods.
public const string CodeAnalysisService_FindReferencesAsync = "FindReferencesAsync";
public const string AssetService_RequestAssetAsync = "RequestAssetAsync";
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册