未验证 提交 a85202d2 编写于 作者: D David 提交者: GitHub

Merge pull request #44474 from dibarbet/lsp_solution

Add ILspSolutionProvider in lsp
......@@ -2,9 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
......@@ -12,10 +16,12 @@
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Composition;
......@@ -30,6 +36,36 @@ namespace Roslyn.Test.Utilities
[UseExportProvider]
public abstract class AbstractLanguageServerProtocolTests
{
[Export(typeof(ILspSolutionProvider)), PartNotDiscoverable]
internal class TestLspSolutionProvider : ILspSolutionProvider
{
[DisallowNull]
private Solution? _currentSolution;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TestLspSolutionProvider()
{
}
public void UpdateSolution(Solution solution)
{
_currentSolution = solution;
}
public Solution GetCurrentSolutionForMainWorkspace()
{
Contract.ThrowIfNull(_currentSolution);
return _currentSolution;
}
public ImmutableArray<Document> GetDocuments(Uri documentUri)
{
Contract.ThrowIfNull(_currentSolution);
return _currentSolution.GetDocuments(documentUri);
}
}
protected virtual ExportProvider GetExportProvider()
{
var requestHelperTypes = DesktopTestHelpers.GetAllTypesImplementingGivenInterface(
......@@ -40,7 +76,8 @@ protected virtual ExportProvider GetExportProvider()
TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic
.WithPart(typeof(LanguageServerProtocol))
.WithParts(requestHelperTypes)
.WithParts(executeCommandHandlerTypes));
.WithParts(executeCommandHandlerTypes)
.WithPart(typeof(TestLspSolutionProvider)));
return exportProviderFactory.CreateExportProvider();
}
......@@ -105,7 +142,7 @@ protected static string ApplyTextEdits(LSP.TextEdit[] edits, SourceText original
return text.ToString();
}
protected static LSP.SymbolInformation CreateSymbolInformation(LSP.SymbolKind kind, string name, LSP.Location location, string containerName = null)
protected static LSP.SymbolInformation CreateSymbolInformation(LSP.SymbolKind kind, string name, LSP.Location location, string? containerName = null)
=> new LSP.SymbolInformation()
{
Kind = kind,
......@@ -114,7 +151,7 @@ protected static LSP.SymbolInformation CreateSymbolInformation(LSP.SymbolKind ki
ContainerName = containerName
};
protected static LSP.TextDocumentIdentifier CreateTextDocumentIdentifier(Uri uri, ProjectId projectContext = null)
protected static LSP.TextDocumentIdentifier CreateTextDocumentIdentifier(Uri uri, ProjectId? projectContext = null)
{
var documentIdentifier = new LSP.VSTextDocumentIdentifier() { Uri = uri };
......@@ -127,7 +164,7 @@ protected static LSP.TextDocumentIdentifier CreateTextDocumentIdentifier(Uri uri
return documentIdentifier;
}
protected static LSP.TextDocumentPositionParams CreateTextDocumentPositionParams(LSP.Location caret, ProjectId projectContext = null)
protected static LSP.TextDocumentPositionParams CreateTextDocumentPositionParams(LSP.Location caret, ProjectId? projectContext = null)
=> new LSP.TextDocumentPositionParams()
{
TextDocument = CreateTextDocumentIdentifier(caret.Uri, projectContext),
......@@ -207,6 +244,8 @@ protected Workspace CreateTestWorkspace(string[] markups, out Dictionary<string,
workspace.ChangeSolution(solution);
locations = GetAnnotatedLocations(workspace, solution);
UpdateSolutionProvider(workspace, solution);
return workspace;
}
......@@ -214,15 +253,22 @@ protected TestWorkspace CreateXmlTestWorkspace(string xmlContent, out Dictionary
{
var workspace = TestWorkspace.Create(xmlContent, exportProvider: GetExportProvider());
locations = GetAnnotatedLocations(workspace, workspace.CurrentSolution);
UpdateSolutionProvider(workspace, workspace.CurrentSolution);
return workspace;
}
private void UpdateSolutionProvider(TestWorkspace workspace, Solution solution)
{
var provider = (TestLspSolutionProvider)workspace.ExportProvider.GetExportedValue<ILspSolutionProvider>();
provider.UpdateSolution(solution);
}
private Dictionary<string, IList<LSP.Location>> GetAnnotatedLocations(TestWorkspace workspace, Solution solution)
{
var locations = new Dictionary<string, IList<LSP.Location>>();
foreach (var testDocument in workspace.Documents)
{
var document = solution.GetDocument(testDocument.Id);
var document = solution.GetRequiredDocument(testDocument.Id);
var text = document.GetTextSynchronously(CancellationToken.None);
foreach (var (name, spans) in testDocument.AnnotatedSpans)
{
......
......@@ -25,19 +25,24 @@ public static Uri GetURI(this Document document)
return ProtocolConversions.GetUriFromFilePath(document.FilePath);
}
public static ImmutableArray<Document> GetDocuments(this Solution solution, Uri uri, string? clientName = null)
public static ImmutableArray<Document> GetDocuments(this Solution solution, Uri documentUri)
{
// TODO: we need to normalize this. but for now, we check both absolute and local path
// right now, based on who calls this, solution might has "/" or "\\" as directory
// separator
var documentIds = solution.GetDocumentIdsWithFilePath(uri.AbsolutePath);
var documentIds = solution.GetDocumentIdsWithFilePath(documentUri.AbsolutePath);
if (!documentIds.Any())
{
documentIds = solution.GetDocumentIdsWithFilePath(uri.LocalPath);
documentIds = solution.GetDocumentIdsWithFilePath(documentUri.LocalPath);
}
var documents = documentIds.SelectAsArray(id => solution.GetRequiredDocument(id));
return documentIds.SelectAsArray(id => solution.GetRequiredDocument(id));
}
public static ImmutableArray<Document> GetDocuments(this ILspSolutionProvider solutionProvider, Uri uri, string? clientName)
{
var documents = solutionProvider.GetDocuments(uri);
// If we don't have a client name, then we're done filtering
if (clientName == null)
......@@ -58,9 +63,9 @@ public static ImmutableArray<Document> GetDocuments(this Solution solution, Uri
});
}
public static Document? GetDocument(this Solution solution, TextDocumentIdentifier documentIdentifier, string? clientName = null)
public static Document? GetDocument(this ILspSolutionProvider solutionProvider, TextDocumentIdentifier documentIdentifier, string? clientName = null)
{
var documents = solution.GetDocuments(documentIdentifier.Uri, clientName);
var documents = solutionProvider.GetDocuments(documentIdentifier.Uri, clientName);
if (documents.Length == 0)
{
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
internal abstract class AbstractRequestHandler<RequestType, ResponseType> : IRequestHandler<RequestType, ResponseType>
{
protected readonly ILspSolutionProvider SolutionProvider;
protected AbstractRequestHandler(ILspSolutionProvider solutionProvider)
{
SolutionProvider = solutionProvider;
}
public abstract Task<ResponseType> HandleRequestAsync(RequestType request, ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken);
}
}
......@@ -5,6 +5,8 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
......@@ -24,21 +26,31 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
/// </summary>
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentCodeActionName)]
internal class CodeActionsHandler : CodeActionsHandlerBase, IRequestHandler<LSP.CodeActionParams, LSP.SumType<LSP.Command, LSP.CodeAction>[]>
internal class CodeActionsHandler : AbstractRequestHandler<LSP.CodeActionParams, LSP.SumType<LSP.Command, LSP.CodeAction>[]>
{
private readonly ICodeFixService _codeFixService;
private readonly ICodeRefactoringService _codeRefactoringService;
internal const string RunCodeActionCommandName = "Roslyn.RunCodeAction";
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public CodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
: base(solutionProvider)
{
_codeFixService = codeFixService;
_codeRefactoringService = codeRefactoringService;
}
public async Task<LSP.SumType<LSP.Command, LSP.CodeAction>[]> HandleRequestAsync(Solution solution, LSP.CodeActionParams request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<LSP.SumType<LSP.Command, LSP.CodeAction>[]> HandleRequestAsync(LSP.CodeActionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var codeActions = await GetCodeActionsAsync(solution,
request.TextDocument,
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
var codeActions = await GetCodeActionsAsync(document,
_codeFixService,
_codeRefactoringService,
request.Range,
clientName, cancellationToken).ConfigureAwait(false);
cancellationToken).ConfigureAwait(false);
// Filter out code actions with options since they'll show dialogs and we can't remote the UI and the options.
codeActions = codeActions.Where(c => !(c is CodeActionWithOptions));
......@@ -72,5 +84,32 @@ public CodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringServic
return result.ToArrayAndFree();
}
internal static async Task<IEnumerable<CodeAction>> GetCodeActionsAsync(Document? document,
ICodeFixService codeFixService,
ICodeRefactoringService codeRefactoringService,
LSP.Range selection,
CancellationToken cancellationToken)
{
if (document == null)
{
return ImmutableArray<CodeAction>.Empty;
}
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var textSpan = ProtocolConversions.RangeToTextSpan(selection, text);
var codeFixCollections = await codeFixService.GetFixesAsync(document, textSpan, true, cancellationToken).ConfigureAwait(false);
var codeRefactorings = await codeRefactoringService.GetRefactoringsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
var codeActions = codeFixCollections.SelectMany(c => c.Fixes.Select(f => f.Action)).Concat(
codeRefactorings.SelectMany(r => r.CodeActions.Select(ca => ca.action)));
// Flatten out the nested codeactions.
var nestedCodeActions = codeActions.Where(c => c is CodeAction.CodeActionWithNestedActions nc && nc.IsInlinable).SelectMany(nc => nc.NestedCodeActions);
codeActions = codeActions.Where(c => !(c is CodeAction.CodeActionWithNestedActions)).Concat(nestedCodeActions);
return codeActions;
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
internal abstract class CodeActionsHandlerBase
{
private readonly ICodeFixService _codeFixService;
private readonly ICodeRefactoringService _codeRefactoringService;
protected const string RunCodeActionCommandName = "Roslyn.RunCodeAction";
public CodeActionsHandlerBase(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
{
_codeFixService = codeFixService ?? throw new ArgumentNullException(nameof(codeFixService));
_codeRefactoringService = codeRefactoringService ?? throw new ArgumentNullException(nameof(codeRefactoringService));
}
public async Task<IEnumerable<CodeAction>> GetCodeActionsAsync(Solution solution, LSP.TextDocumentIdentifier documentIdentifier, LSP.Range selection, string? clientName, CancellationToken cancellationToken)
{
var document = solution.GetDocument(documentIdentifier, clientName);
if (document == null)
{
return ImmutableArray<CodeAction>.Empty;
}
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var textSpan = ProtocolConversions.RangeToTextSpan(selection, text);
var codeFixCollections = await _codeFixService.GetFixesAsync(document, textSpan, true, cancellationToken).ConfigureAwait(false);
var codeRefactorings = await _codeRefactoringService.GetRefactoringsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
var codeActions = codeFixCollections.SelectMany(c => c.Fixes.Select(f => f.Action)).Concat(
codeRefactorings.SelectMany(r => r.CodeActions.Select(ca => ca.action)));
// Flatten out the nested codeactions.
var nestedCodeActions = codeActions.Where(c => c is CodeAction.CodeActionWithNestedActions nc && nc.IsInlinable).SelectMany(nc => nc.NestedCodeActions);
codeActions = codeActions.Where(c => !(c is CodeAction.CodeActionWithNestedActions)).Concat(nestedCodeActions);
return codeActions;
}
}
}
......@@ -43,8 +43,8 @@ public ExecuteWorkspaceCommandHandler([ImportMany] IEnumerable<Lazy<IExecuteWork
/// Handles an <see cref="LSP.Methods.WorkspaceExecuteCommand"/>
/// by delegating to a handler for the specific command requested.
/// </summary>
public Task<object> HandleRequestAsync(Solution solution, LSP.ExecuteCommandParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
public Task<object> HandleRequestAsync(LSP.ExecuteCommandParams request, LSP.ClientCapabilities clientCapabilities, string? clientName,
CancellationToken cancellationToken)
{
var commandName = request.Command;
if (string.IsNullOrEmpty(commandName) || !_executeCommandHandlers.TryGetValue(commandName, out var executeCommandHandler))
......@@ -52,7 +52,7 @@ public ExecuteWorkspaceCommandHandler([ImportMany] IEnumerable<Lazy<IExecuteWork
throw new ArgumentException(string.Format("Command name ({0}) is invalid", commandName));
}
return executeCommandHandler.Value.HandleRequestAsync(solution, request, clientCapabilities, cancellationToken);
return executeCommandHandler.Value.HandleRequestAsync(request, clientCapabilities, cancellationToken);
}
}
}
......@@ -13,6 +13,6 @@ internal interface IExecuteWorkspaceCommandHandler
/// <summary>
/// Handles a specific command from a <see cref="Methods.WorkspaceExecuteCommandName"/> request.
/// </summary>
Task<object> HandleRequestAsync(Solution solution, ExecuteCommandParams request, ClientCapabilities clientCapabilities, CancellationToken cancellationToken);
Task<object> HandleRequestAsync(ExecuteCommandParams request, ClientCapabilities clientCapabilities, CancellationToken cancellationToken);
}
}
......@@ -24,18 +24,18 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
/// </summary>
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentCompletionName)]
internal class CompletionHandler : IRequestHandler<LSP.CompletionParams, LSP.CompletionItem[]>
internal class CompletionHandler : AbstractRequestHandler<LSP.CompletionParams, LSP.CompletionItem[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CompletionHandler()
public CompletionHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<LSP.CompletionItem[]> HandleRequestAsync(Solution solution, LSP.CompletionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
public override async Task<LSP.CompletionItem[]> HandleRequestAsync(LSP.CompletionParams request, LSP.ClientCapabilities clientCapabilities, string? clientName,
CancellationToken cancellationToken)
{
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return Array.Empty<LSP.CompletionItem>();
......
......@@ -23,16 +23,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
/// </summary>
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentCompletionResolveName)]
internal class CompletionResolveHandler : IRequestHandler<LSP.CompletionItem, LSP.CompletionItem>
internal class CompletionResolveHandler : AbstractRequestHandler<LSP.CompletionItem, LSP.CompletionItem>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CompletionResolveHandler()
public CompletionResolveHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<LSP.CompletionItem> HandleRequestAsync(Solution solution, LSP.CompletionItem completionItem,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<LSP.CompletionItem> HandleRequestAsync(LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
CompletionResolveData data;
if (completionItem.Data is CompletionResolveData)
......@@ -46,7 +46,7 @@ public CompletionResolveHandler()
var request = data.CompletionParams;
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return completionItem;
......
......@@ -17,18 +17,18 @@
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
internal class GoToDefinitionHandlerBase
internal abstract class AbstractGoToDefinitionHandler<RequestType, ResponseType> : AbstractRequestHandler<RequestType, ResponseType>
{
private readonly IMetadataAsSourceFileService _metadataAsSourceFileService;
public GoToDefinitionHandlerBase(IMetadataAsSourceFileService metadataAsSourceFileService)
public AbstractGoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileService, ILspSolutionProvider solutionProvider) : base(solutionProvider)
=> _metadataAsSourceFileService = metadataAsSourceFileService;
protected async Task<LSP.Location[]> GetDefinitionAsync(Solution solution, LSP.TextDocumentPositionParams request, bool typeOnly, string? clientName, CancellationToken cancellationToken)
protected async Task<LSP.Location[]> GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, string? clientName, CancellationToken cancellationToken)
{
var locations = ArrayBuilder<LSP.Location>.GetInstance();
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return locations.ToArrayAndFree();
......
......@@ -16,16 +16,17 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentDefinitionName)]
internal class GoToDefinitionHandler : GoToDefinitionHandlerBase, IRequestHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
internal class GoToDefinitionHandler : AbstractGoToDefinitionHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public GoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileService) : base(metadataAsSourceFileService)
public GoToDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileService, ILspSolutionProvider solutionProvider)
: base(metadataAsSourceFileService, solutionProvider)
{
}
public Task<LSP.Location[]> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
=> GetDefinitionAsync(solution, request, typeOnly: false, clientName, cancellationToken: cancellationToken);
public override Task<LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
=> GetDefinitionAsync(request, typeOnly: false, clientName, cancellationToken: cancellationToken);
}
}
......@@ -16,18 +16,17 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentTypeDefinitionName)]
internal class GoToTypeDefinitionHandler : GoToDefinitionHandlerBase, IRequestHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
internal class GoToTypeDefinitionHandler : AbstractGoToDefinitionHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public GoToTypeDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileService) : base(metadataAsSourceFileService)
public GoToTypeDefinitionHandler(IMetadataAsSourceFileService metadataAsSourceFileService, ILspSolutionProvider solutionProvider)
: base(metadataAsSourceFileService, solutionProvider)
{
}
public async Task<LSP.Location[]> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
{
return await GetDefinitionAsync(solution, request, typeOnly: true, clientName, cancellationToken: cancellationToken).ConfigureAwait(false);
}
public override Task<LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
=> GetDefinitionAsync(request, typeOnly: true, clientName, cancellationToken: cancellationToken);
}
}
......@@ -17,20 +17,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentFoldingRangeName)]
internal class FoldingRangesHandler : IRequestHandler<FoldingRangeParams, FoldingRange[]>
internal class FoldingRangesHandler : AbstractRequestHandler<FoldingRangeParams, FoldingRange[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FoldingRangesHandler()
public FoldingRangesHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<FoldingRange[]> HandleRequestAsync(Solution solution, FoldingRangeParams request,
ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<FoldingRange[]> HandleRequestAsync(FoldingRangeParams request, ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var foldingRanges = ArrayBuilder<FoldingRange>.GetInstance();
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return foldingRanges.ToArrayAndFree();
......
......@@ -15,12 +15,16 @@
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
internal abstract class FormatDocumentHandlerBase
internal abstract class AbstractFormatDocumentHandlerBase<RequestType, ResponseType> : AbstractRequestHandler<RequestType, ResponseType>
{
protected async Task<LSP.TextEdit[]> GetTextEditsAsync(Solution solution, LSP.TextDocumentIdentifier documentIdentifier, string? clientName, CancellationToken cancellationToken, LSP.Range? range = null)
protected AbstractFormatDocumentHandlerBase(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
protected async Task<LSP.TextEdit[]> GetTextEditsAsync(LSP.TextDocumentIdentifier documentIdentifier, string? clientName, CancellationToken cancellationToken, LSP.Range? range = null)
{
var edits = new ArrayBuilder<LSP.TextEdit>();
var document = solution.GetDocument(documentIdentifier, clientName);
var document = SolutionProvider.GetDocument(documentIdentifier, clientName);
if (document != null)
{
......
......@@ -15,18 +15,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentFormattingName)]
internal class FormatDocumentHandler : FormatDocumentHandlerBase, IRequestHandler<LSP.DocumentFormattingParams, LSP.TextEdit[]>
internal class FormatDocumentHandler : AbstractFormatDocumentHandlerBase<LSP.DocumentFormattingParams, LSP.TextEdit[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FormatDocumentHandler()
public FormatDocumentHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<LSP.TextEdit[]> HandleRequestAsync(Solution solution, LSP.DocumentFormattingParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
return await GetTextEditsAsync(solution, request.TextDocument, clientName, cancellationToken).ConfigureAwait(false);
}
public override Task<LSP.TextEdit[]> HandleRequestAsync(LSP.DocumentFormattingParams request, LSP.ClientCapabilities clientCapabilities, string? clientName,
CancellationToken cancellationToken)
=> GetTextEditsAsync(request.TextDocument, clientName, cancellationToken);
}
}
......@@ -21,19 +21,19 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentOnTypeFormattingName)]
internal class FormatDocumentOnTypeHandler : IRequestHandler<DocumentOnTypeFormattingParams, TextEdit[]>
internal class FormatDocumentOnTypeHandler : AbstractRequestHandler<DocumentOnTypeFormattingParams, TextEdit[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FormatDocumentOnTypeHandler()
public FormatDocumentOnTypeHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<TextEdit[]> HandleRequestAsync(Solution solution, DocumentOnTypeFormattingParams request, ClientCapabilities? clientCapabilities,
string? clientName, CancellationToken cancellationToken)
public override async Task<TextEdit[]> HandleRequestAsync(DocumentOnTypeFormattingParams request, ClientCapabilities? clientCapabilities, string? clientName,
CancellationToken cancellationToken)
{
var edits = new ArrayBuilder<TextEdit>();
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document != null)
{
var formattingService = document.Project.LanguageServices.GetRequiredService<IEditorFormattingService>();
......
......@@ -15,18 +15,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentRangeFormattingName)]
internal class FormatDocumentRangeHandler : FormatDocumentHandlerBase, IRequestHandler<DocumentRangeFormattingParams, TextEdit[]>
internal class FormatDocumentRangeHandler : AbstractFormatDocumentHandlerBase<DocumentRangeFormattingParams, TextEdit[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FormatDocumentRangeHandler()
public FormatDocumentRangeHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<TextEdit[]> HandleRequestAsync(Solution solution, DocumentRangeFormattingParams request, ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
return await GetTextEditsAsync(solution, request.TextDocument, clientName, cancellationToken, range: request.Range).ConfigureAwait(false);
}
public override Task<TextEdit[]> HandleRequestAsync(DocumentRangeFormattingParams request, ClientCapabilities clientCapabilities, string? clientName,
CancellationToken cancellationToken)
=> GetTextEditsAsync(request.TextDocument, clientName, cancellationToken, range: request.Range);
}
}
......@@ -18,18 +18,18 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentDocumentHighlightName)]
internal class DocumentHighlightsHandler : IRequestHandler<TextDocumentPositionParams, DocumentHighlight[]>
internal class DocumentHighlightsHandler : AbstractRequestHandler<TextDocumentPositionParams, DocumentHighlight[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public DocumentHighlightsHandler()
public DocumentHighlightsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<DocumentHighlight[]> HandleRequestAsync(Solution solution, TextDocumentPositionParams request,
ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<DocumentHighlight[]> HandleRequestAsync(TextDocumentPositionParams request, ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return Array.Empty<DocumentHighlight>();
......
......@@ -17,18 +17,18 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentHoverName)]
internal class HoverHandler : IRequestHandler<TextDocumentPositionParams, Hover?>
internal class HoverHandler : AbstractRequestHandler<TextDocumentPositionParams, Hover?>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public HoverHandler()
public HoverHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<Hover?> HandleRequestAsync(Solution solution, TextDocumentPositionParams request,
ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<Hover?> HandleRequestAsync(TextDocumentPositionParams request, ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return null;
......
......@@ -22,12 +22,11 @@ internal interface IRequestHandler<RequestType, ResponseType> : IRequestHandler
/// <summary>
/// Handles an LSP request.
/// </summary>
/// <param name="solution">the solution to apply the request to.</param>
/// <param name="request">the lsp request.</param>
/// <param name="clientCapabilities">the client capabilities for the request.</param>
/// <param name="clientName">the lsp client making the request.</param>
/// <returns>the LSP response.</returns>
/// <param name="cancellationToken">a cancellation token.</param>
Task<ResponseType> HandleRequestAsync(Solution solution, RequestType request, ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken);
/// <returns>the LSP response.</returns>
Task<ResponseType> HandleRequestAsync(RequestType request, ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken);
}
}
......@@ -33,7 +33,7 @@ public InitializeHandler([ImportMany] IEnumerable<Lazy<CompletionProvider, Compl
.ToImmutableArray();
}
public Task<LSP.InitializeResult> HandleRequestAsync(Solution solution, LSP.InitializeParams request, LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public Task<LSP.InitializeResult> HandleRequestAsync(LSP.InitializeParams request, LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
{
var triggerCharacters = _completionProviders.SelectMany(lz => GetTriggerCharacters(lz.Value)).Distinct().Select(c => c.ToString()).ToArray();
......
......@@ -18,22 +18,21 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(MSLSPMethods.ProjectContextsName)]
internal class GetTextDocumentWithContextHandler : IRequestHandler<GetTextDocumentWithContextParams, ActiveProjectContexts?>
internal class GetTextDocumentWithContextHandler : AbstractRequestHandler<GetTextDocumentWithContextParams, ActiveProjectContexts?>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public GetTextDocumentWithContextHandler()
public GetTextDocumentWithContextHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public Task<ActiveProjectContexts?> HandleRequestAsync(
Solution solution,
public override Task<ActiveProjectContexts?> HandleRequestAsync(
GetTextDocumentWithContextParams request,
ClientCapabilities clientCapabilities,
string? clientName,
CancellationToken cancellationToken)
{
var documents = solution.GetDocuments(request.TextDocument.Uri, clientName);
var documents = SolutionProvider.GetDocuments(request.TextDocument.Uri, clientName);
if (!documents.Any())
{
......@@ -68,7 +67,8 @@ public GetTextDocumentWithContextHandler()
// GetDocumentIdInCurrentContext will just return the same ID back, which means we're going to pick the first
// ID in GetDocumentIdsWithFilePath, but there's really nothing we can do since we don't have contexts for
// close documents anyways.
var currentContextDocumentId = solution.Workspace.GetDocumentIdInCurrentContext(documents.First().Id);
var openDocument = documents.First();
var currentContextDocumentId = openDocument.Project.Solution.Workspace.GetDocumentIdInCurrentContext(openDocument.Id);
return Task.FromResult<ActiveProjectContexts?>(new ActiveProjectContexts
{
......
......@@ -20,19 +20,18 @@
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[ExportLspMethod(LSP.Methods.TextDocumentReferencesName), Shared]
internal class FindAllReferencesHandler : IRequestHandler<LSP.ReferenceParams, LSP.VSReferenceItem[]>
internal class FindAllReferencesHandler : AbstractRequestHandler<LSP.ReferenceParams, LSP.VSReferenceItem[]>
{
private readonly IMetadataAsSourceFileService _metadataAsSourceFileService;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FindAllReferencesHandler(IMetadataAsSourceFileService metadataAsSourceFileService)
public FindAllReferencesHandler(IMetadataAsSourceFileService metadataAsSourceFileService, ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
_metadataAsSourceFileService = metadataAsSourceFileService;
}
public async Task<LSP.VSReferenceItem[]> HandleRequestAsync(
Solution solution,
public override async Task<LSP.VSReferenceItem[]> HandleRequestAsync(
ReferenceParams referenceParams,
ClientCapabilities clientCapabilities,
string? clientName,
......@@ -40,7 +39,7 @@ public FindAllReferencesHandler(IMetadataAsSourceFileService metadataAsSourceFil
{
Debug.Assert(clientCapabilities.HasVisualStudioLspCapability());
var document = solution.GetDocument(referenceParams.TextDocument, clientName);
var document = SolutionProvider.GetDocument(referenceParams.TextDocument, clientName);
if (document == null)
{
return Array.Empty<LSP.VSReferenceItem>();
......
......@@ -17,20 +17,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentImplementationName)]
internal class FindImplementationsHandler : IRequestHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
internal class FindImplementationsHandler : AbstractRequestHandler<LSP.TextDocumentPositionParams, LSP.Location[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public FindImplementationsHandler()
public FindImplementationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<LSP.Location[]> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<LSP.Location[]> HandleRequestAsync(LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var locations = ArrayBuilder<LSP.Location>.GetInstance();
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return locations.ToArrayAndFree();
......
......@@ -20,20 +20,21 @@
namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[ExportLspMethod(LSP.Methods.TextDocumentRenameName), Shared]
internal class RenameHandler : IRequestHandler<LSP.RenameParams, WorkspaceEdit?>
internal class RenameHandler : AbstractRequestHandler<LSP.RenameParams, WorkspaceEdit?>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RenameHandler()
public RenameHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<WorkspaceEdit?> HandleRequestAsync(Solution oldSolution, RenameParams request, ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<WorkspaceEdit?> HandleRequestAsync(RenameParams request, ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
{
WorkspaceEdit? workspaceEdit = null;
var document = oldSolution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document != null)
{
var oldSolution = document.Project.Solution;
var renameService = document.Project.LanguageServices.GetRequiredService<IEditorInlineRenameService>();
var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);
......
......@@ -21,19 +21,20 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(LSP.Methods.TextDocumentSignatureHelpName)]
internal class SignatureHelpHandler : IRequestHandler<LSP.TextDocumentPositionParams, LSP.SignatureHelp>
internal class SignatureHelpHandler : AbstractRequestHandler<LSP.TextDocumentPositionParams, LSP.SignatureHelp>
{
private readonly IEnumerable<Lazy<ISignatureHelpProvider, OrderableLanguageMetadata>> _allProviders;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public SignatureHelpHandler([ImportMany] IEnumerable<Lazy<ISignatureHelpProvider, OrderableLanguageMetadata>> allProviders)
public SignatureHelpHandler([ImportMany] IEnumerable<Lazy<ISignatureHelpProvider, OrderableLanguageMetadata>> allProviders, ILspSolutionProvider solutionProvider)
: base(solutionProvider)
=> _allProviders = allProviders;
public async Task<LSP.SignatureHelp> HandleRequestAsync(Solution solution, LSP.TextDocumentPositionParams request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<LSP.SignatureHelp> HandleRequestAsync(LSP.TextDocumentPositionParams request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return new LSP.SignatureHelp();
......
......@@ -21,18 +21,18 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.TextDocumentDocumentSymbolName)]
internal class DocumentSymbolsHandler : IRequestHandler<DocumentSymbolParams, object[]>
internal class DocumentSymbolsHandler : AbstractRequestHandler<DocumentSymbolParams, object[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public DocumentSymbolsHandler()
public DocumentSymbolsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<object[]> HandleRequestAsync(Solution solution, DocumentSymbolParams request,
ClientCapabilities clientCapabilities, string clientName, CancellationToken cancellationToken)
public override async Task<object[]> HandleRequestAsync(DocumentSymbolParams request, ClientCapabilities clientCapabilities,
string clientName, CancellationToken cancellationToken)
{
var document = solution.GetDocument(request.TextDocument, clientName);
var document = SolutionProvider.GetDocument(request.TextDocument, clientName);
if (document == null)
{
return Array.Empty<SymbolInformation>();
......
......@@ -18,17 +18,18 @@ namespace Microsoft.CodeAnalysis.LanguageServer.Handler
{
[Shared]
[ExportLspMethod(Methods.WorkspaceSymbolName)]
internal class WorkspaceSymbolsHandler : IRequestHandler<WorkspaceSymbolParams, SymbolInformation[]>
internal class WorkspaceSymbolsHandler : AbstractRequestHandler<WorkspaceSymbolParams, SymbolInformation[]>
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public WorkspaceSymbolsHandler()
public WorkspaceSymbolsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public async Task<SymbolInformation[]> HandleRequestAsync(Solution solution, WorkspaceSymbolParams request,
ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken)
public override async Task<SymbolInformation[]> HandleRequestAsync(WorkspaceSymbolParams request, ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken)
{
var solution = SolutionProvider.GetCurrentSolutionForMainWorkspace();
var searchTasks = Task.WhenAll(solution.Projects.Select(project => SearchProjectAsync(project, request, cancellationToken)));
return (await searchTasks.ConfigureAwait(false)).SelectMany(s => s).ToArray();
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.LanguageServer
{
internal interface ILspSolutionProvider
{
/// <summary>
/// Finds the workspace and solution containing the specified document URI
/// and returns the documents in that context.
/// </summary>
/// <param name="documentUri">the document's file path URI.</param>
/// <returns>the documents in the correct workspace and solution context</returns>
ImmutableArray<Document> GetDocuments(Uri documentUri);
/// <summary>
/// Return the latest solution from the main workspace that we know about.
/// </summary>
Solution GetCurrentSolutionForMainWorkspace();
}
}
......@@ -43,17 +43,16 @@ public LanguageServerProtocol([ImportMany] IEnumerable<Lazy<IRequestHandler, IRe
return requestHandlerDictionary.ToImmutable();
}
public Task<ResponseType> ExecuteRequestAsync<RequestType, ResponseType>(string methodName, Solution solution, RequestType request,
LSP.ClientCapabilities clientCapabilities, string? clientName, CancellationToken cancellationToken) where RequestType : class
public Task<ResponseType> ExecuteRequestAsync<RequestType, ResponseType>(string methodName, RequestType request, LSP.ClientCapabilities clientCapabilities,
string? clientName, CancellationToken cancellationToken) where RequestType : class
{
Contract.ThrowIfNull(solution);
Contract.ThrowIfNull(request);
Contract.ThrowIfTrue(string.IsNullOrEmpty(methodName), "Invalid method name");
var handler = (IRequestHandler<RequestType, ResponseType>?)_requestHandlers[methodName]?.Value;
Contract.ThrowIfNull(handler, string.Format("Request handler not found for method {0}", methodName));
return handler.HandleRequestAsync(solution, request, clientCapabilities, clientName, cancellationToken);
return handler.HandleRequestAsync(request, clientCapabilities, clientName, cancellationToken);
}
}
}
......@@ -38,7 +38,7 @@ void M()
private static async Task<LSP.Command[]> RunGetCodeActionsAsync(Solution solution, LSP.Location caret, LSP.ClientCapabilities clientCapabilities = null)
{
var results = await GetLanguageServer(solution).ExecuteRequestAsync<LSP.CodeActionParams, LSP.SumType<LSP.Command, LSP.CodeAction>[]>(LSP.Methods.TextDocumentCodeActionName,
solution, CreateCodeActionParams(caret), clientCapabilities, null, CancellationToken.None);
CreateCodeActionParams(caret), clientCapabilities, null, CancellationToken.None);
return results.Select(r => (LSP.Command)r).ToArray();
}
......
......@@ -40,7 +40,7 @@ void M()
private static async Task<object> RunResolveCompletionItemAsync(Solution solution, LSP.CompletionItem completionItem, LSP.ClientCapabilities clientCapabilities = null)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.CompletionItem, LSP.CompletionItem>(LSP.Methods.TextDocumentCompletionResolveName,
solution, completionItem, clientCapabilities, null, CancellationToken.None);
completionItem, clientCapabilities, null, CancellationToken.None);
private static LSP.VSCompletionItem CreateResolvedCompletionItem(string text, LSP.CompletionItemKind kind, string[] tags, LSP.CompletionParams requestParameters,
ClassifiedTextElement description, string detail, string documentation)
......
......@@ -62,6 +62,6 @@ void M()
private static async Task<LSP.CompletionItem[]> RunGetCompletionsAsync(Solution solution, LSP.Location caret, LSP.ClientCapabilities clientCapabilities = null)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.CompletionParams, LSP.CompletionItem[]>(LSP.Methods.TextDocumentCompletionName,
solution, CreateCompletionParams(caret), clientCapabilities, null, CancellationToken.None);
CreateCompletionParams(caret), clientCapabilities, null, CancellationToken.None);
}
}
......@@ -77,6 +77,6 @@ void M()
private static async Task<LSP.Location[]> RunGotoDefinitionAsync(Solution solution, LSP.Location caret)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.Location[]>(LSP.Methods.TextDocumentDefinitionName,
solution, CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
}
}
......@@ -76,6 +76,6 @@ class B
private static async Task<LSP.Location[]> RunGotoTypeDefinitionAsync(Solution solution, LSP.Location caret)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.Location[]>(LSP.Methods.TextDocumentTypeDefinitionName,
solution, CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
}
}
......@@ -70,7 +70,7 @@ private static async Task<LSP.FoldingRange[]> RunGetFoldingRangeAsync(Solution s
};
return await GetLanguageServer(solution).ExecuteRequestAsync<LSP.FoldingRangeParams, LSP.FoldingRange[]>(LSP.Methods.TextDocumentFoldingRangeName,
solution, request, new LSP.ClientCapabilities(), null, CancellationToken.None);
request, new LSP.ClientCapabilities(), null, CancellationToken.None);
}
private static LSP.FoldingRange CreateFoldingRange(LSP.FoldingRangeKind kind, LSP.Range range)
......
......@@ -47,7 +47,7 @@ void M()
private static async Task<LSP.TextEdit[]> RunFormatDocumentOnTypeAsync(Solution solution, string characterTyped, LSP.Location locationTyped)
=> await GetLanguageServer(solution)
.ExecuteRequestAsync<LSP.DocumentOnTypeFormattingParams, LSP.TextEdit[]>(LSP.Methods.TextDocumentOnTypeFormattingName,
solution, CreateDocumentOnTypeFormattingParams(characterTyped, locationTyped), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateDocumentOnTypeFormattingParams(characterTyped, locationTyped), new LSP.ClientCapabilities(), null, CancellationToken.None);
private static LSP.DocumentOnTypeFormattingParams CreateDocumentOnTypeFormattingParams(string characterTyped, LSP.Location locationTyped)
=> new LSP.DocumentOnTypeFormattingParams()
......
......@@ -43,7 +43,7 @@ void M()
private static async Task<LSP.TextEdit[]> RunFormatDocumentRangeAsync(Solution solution, LSP.Location location)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.DocumentRangeFormattingParams, LSP.TextEdit[]>(LSP.Methods.TextDocumentRangeFormattingName,
solution, CreateDocumentRangeFormattingParams(location), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateDocumentRangeFormattingParams(location), new LSP.ClientCapabilities(), null, CancellationToken.None);
private static LSP.DocumentRangeFormattingParams CreateDocumentRangeFormattingParams(LSP.Location location)
=> new LSP.DocumentRangeFormattingParams()
......
......@@ -44,7 +44,7 @@ void M()
private static async Task<LSP.TextEdit[]> RunFormatDocumentAsync(Solution solution, Uri uri)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.DocumentFormattingParams, LSP.TextEdit[]>(LSP.Methods.TextDocumentFormattingName,
solution, CreateDocumentFormattingParams(uri), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateDocumentFormattingParams(uri), new LSP.ClientCapabilities(), null, CancellationToken.None);
private static LSP.DocumentFormattingParams CreateDocumentFormattingParams(Uri uri)
=> new LSP.DocumentFormattingParams()
......
......@@ -62,7 +62,7 @@ void M()
private static async Task<LSP.DocumentHighlight[]> RunGetDocumentHighlightAsync(Solution solution, LSP.Location caret)
{
var results = await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.DocumentHighlight[]>(LSP.Methods.TextDocumentDocumentHighlightName,
solution, CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
Array.Sort(results, (h1, h2) =>
{
var compareKind = h1.Kind.CompareTo(h2.Kind);
......
......@@ -194,7 +194,7 @@ static void Main(string[] args)
private static async Task<LSP.Hover> RunGetHoverAsync(Solution solution, LSP.Location caret, ProjectId projectContext = null)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.Hover>(LSP.Methods.TextDocumentHoverName,
solution, CreateTextDocumentPositionParams(caret, projectContext), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret, projectContext), new LSP.ClientCapabilities(), null, CancellationToken.None);
private static LSP.Hover CreateHover(LSP.Location location, string text)
=> new LSP.Hover()
......
......@@ -24,7 +24,7 @@ public async Task TestInitializeAsync()
private static async Task<LSP.InitializeResult> RunInitializeAsync(Solution solution, LSP.InitializeParams request)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.InitializeParams, LSP.InitializeResult>(LSP.Methods.InitializeName,
solution, request, new LSP.ClientCapabilities(), null, CancellationToken.None);
request, new LSP.ClientCapabilities(), null, CancellationToken.None);
private static void AssertServerCapabilities(LSP.ServerCapabilities actual)
{
......
......@@ -98,7 +98,7 @@ public async Task SwitchingContextsChangesDefaultContext()
private static async Task<LSP.ActiveProjectContexts?> RunGetProjectContext(Solution solution, Uri uri)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.GetTextDocumentWithContextParams, LSP.ActiveProjectContexts?>(LSP.MSLSPMethods.ProjectContextsName,
solution, CreateGetProjectContextParams(uri), new LSP.ClientCapabilities(), clientName: null, CancellationToken.None);
CreateGetProjectContextParams(uri), new LSP.ClientCapabilities(), clientName: null, cancellationToken: CancellationToken.None);
private static LSP.GetTextDocumentWithContextParams CreateGetProjectContextParams(Uri uri)
=> new LSP.GetTextDocumentWithContextParams()
......
......@@ -130,7 +130,7 @@ private static async Task<LSP.VSReferenceItem[]> RunFindAllReferencesAsync(Solut
};
return await GetLanguageServer(solution).ExecuteRequestAsync<LSP.ReferenceParams, LSP.VSReferenceItem[]>(LSP.Methods.TextDocumentReferencesName,
solution, CreateReferenceParams(caret), vsClientCapabilities, null, CancellationToken.None);
CreateReferenceParams(caret), vsClientCapabilities, null, CancellationToken.None);
}
private static void AssertValidDefinitionProperties(LSP.ReferenceItem[] referenceItems, int definitionIndex)
......
......@@ -96,6 +96,6 @@ class {|implementation:C|} : A { }";
private static async Task<LSP.Location[]> RunFindImplementationAsync(Solution solution, LSP.Location caret)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.Location[]>(LSP.Methods.TextDocumentImplementationName,
solution, CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
}
}
......@@ -126,6 +126,6 @@ private static LSP.RenameParams CreateRenameParams(LSP.Location location, string
private static async Task<WorkspaceEdit> RunRenameAsync(Solution solution, LSP.Location renameLocation, string renamevalue)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.RenameParams, LSP.WorkspaceEdit>(LSP.Methods.TextDocumentRenameName,
solution, CreateRenameParams(renameLocation, renamevalue), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateRenameParams(renameLocation, renamevalue), new LSP.ClientCapabilities(), null, CancellationToken.None);
}
}
......@@ -46,7 +46,7 @@ int M2(string a)
private static async Task<LSP.SignatureHelp> RunGetSignatureHelpAsync(Solution solution, LSP.Location caret)
=> await GetLanguageServer(solution).ExecuteRequestAsync<LSP.TextDocumentPositionParams, LSP.SignatureHelp>(LSP.Methods.TextDocumentSignatureHelpName,
solution, CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
CreateTextDocumentPositionParams(caret), new LSP.ClientCapabilities(), null, CancellationToken.None);
private static LSP.SignatureInformation CreateSignatureInformation(string methodLabal, string methodDocumentation, string parameterLabel, string parameterDocumentation)
=> new LSP.SignatureInformation()
......
......@@ -103,7 +103,7 @@ private static async Task<object[]> RunGetDocumentSymbolsAsync(Solution solution
};
return await GetLanguageServer(solution).ExecuteRequestAsync<LSP.DocumentSymbolParams, object[]>(LSP.Methods.TextDocumentDocumentSymbolName,
solution, request, clientCapabilities, null, CancellationToken.None);
request, clientCapabilities, null, CancellationToken.None);
}
private static void AssertDocumentSymbolEquals(LSP.DocumentSymbol expected, LSP.DocumentSymbol actual)
......
......@@ -157,7 +157,7 @@ private static async Task<LSP.SymbolInformation[]> RunGetWorkspaceSymbolsAsync(S
};
return await GetLanguageServer(solution).ExecuteRequestAsync<LSP.WorkspaceSymbolParams, LSP.SymbolInformation[]>(LSP.Methods.WorkspaceSymbolName,
solution, request, new LSP.ClientCapabilities(), null, CancellationToken.None);
request, new LSP.ClientCapabilities(), null, CancellationToken.None);
}
}
}
......@@ -57,8 +57,10 @@ internal abstract class AbstractLanguageServerClient : ILanguageClient
/// </summary>
public event AsyncEventHandler<EventArgs>? StopAsync { add { } remove { } }
public AbstractLanguageServerClient(LanguageServerProtocol languageServerProtocol, VisualStudioWorkspace workspace,
IDiagnosticService diagnosticService, string? diagnosticsClientName)
public AbstractLanguageServerClient(LanguageServerProtocol languageServerProtocol,
VisualStudioWorkspace workspace,
IDiagnosticService diagnosticService,
string? diagnosticsClientName)
{
_languageServerProtocol = languageServerProtocol;
_workspace = workspace;
......@@ -71,7 +73,8 @@ public Task<Connection> ActivateAsync(CancellationToken token)
Contract.ThrowIfFalse(_languageServer == null, "This language server has already been initialized");
var (clientStream, serverStream) = FullDuplexStream.CreatePair();
_languageServer = new InProcLanguageServer(serverStream, serverStream, _languageServerProtocol, _workspace, _diagnosticService, clientName: _diagnosticsClientName);
_languageServer = new InProcLanguageServer(serverStream, serverStream, _languageServerProtocol, _workspace,
_diagnosticService, clientName: _diagnosticsClientName);
return Task.FromResult(new Connection(clientStream, clientStream));
}
......
......@@ -41,8 +41,12 @@ internal class InProcLanguageServer
private VSClientCapabilities _clientCapabilities;
public InProcLanguageServer(Stream inputStream, Stream outputStream, LanguageServerProtocol protocol,
CodeAnalysis.Workspace workspace, IDiagnosticService diagnosticService, string? clientName)
public InProcLanguageServer(Stream inputStream,
Stream outputStream,
LanguageServerProtocol protocol,
CodeAnalysis.Workspace workspace,
IDiagnosticService diagnosticService,
string? clientName)
{
_protocol = protocol;
_workspace = workspace;
......@@ -73,7 +77,7 @@ public async Task<InitializeResult> InitializeAsync(InitializeParams initializeP
_clientCapabilities = (VSClientCapabilities)initializeParams.Capabilities;
var serverCapabilities = await _protocol.ExecuteRequestAsync<InitializeParams, InitializeResult>(Methods.InitializeName,
_workspace.CurrentSolution, initializeParams, _clientCapabilities, _clientName, cancellationToken).ConfigureAwait(false);
initializeParams, _clientCapabilities, _clientName, cancellationToken).ConfigureAwait(false);
// Always support hover - if any LSP client for a content type advertises support,
// then the liveshare provider is disabled. So we must provide for both C# and razor
......@@ -110,78 +114,78 @@ public void Exit()
[JsonRpcMethod(Methods.TextDocumentDefinitionName, UseSingleObjectParameterDeserialization = true)]
public Task<LSP.Location[]> GetTextDocumentDefinitionAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<TextDocumentPositionParams, LSP.Location[]>(Methods.TextDocumentDefinitionName,
_workspace.CurrentSolution, textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentRenameName, UseSingleObjectParameterDeserialization = true)]
public Task<WorkspaceEdit> GetTextDocumentRenameAsync(RenameParams renameParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<RenameParams, WorkspaceEdit>(Methods.TextDocumentRenameName,
_workspace.CurrentSolution, renameParams, _clientCapabilities, _clientName, cancellationToken);
renameParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentReferencesName, UseSingleObjectParameterDeserialization = true)]
public Task<VSReferenceItem[]> GetTextDocumentReferencesAsync(ReferenceParams referencesParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<ReferenceParams, VSReferenceItem[]>(Methods.TextDocumentReferencesName,
_workspace.CurrentSolution, referencesParams, _clientCapabilities, _clientName, cancellationToken);
referencesParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentCompletionName, UseSingleObjectParameterDeserialization = true)]
public async Task<SumType<CompletionList, CompletionItem[]>> GetTextDocumentCompletionAsync(CompletionParams completionParams, CancellationToken cancellationToken)
// Convert to sumtype before reporting to work around https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1107698
=> await _protocol.ExecuteRequestAsync<CompletionParams, CompletionItem[]>(Methods.TextDocumentCompletionName,
_workspace.CurrentSolution, completionParams, _clientCapabilities, _clientName, cancellationToken).ConfigureAwait(false);
completionParams, _clientCapabilities, _clientName, cancellationToken).ConfigureAwait(false);
[JsonRpcMethod(Methods.TextDocumentCompletionResolveName, UseSingleObjectParameterDeserialization = true)]
public Task<CompletionItem> ResolveCompletionItemAsync(CompletionItem completionItem, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<CompletionItem, CompletionItem>(Methods.TextDocumentCompletionResolveName,
_workspace.CurrentSolution, completionItem, _clientCapabilities, _clientName, cancellationToken);
completionItem, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentDocumentHighlightName, UseSingleObjectParameterDeserialization = true)]
public Task<DocumentHighlight[]> GetTextDocumentDocumentHighlightsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<TextDocumentPositionParams, DocumentHighlight[]>(Methods.TextDocumentDocumentHighlightName,
_workspace.CurrentSolution, textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentHoverName, UseSingleObjectParameterDeserialization = true)]
public Task<Hover?> GetTextDocumentDocumentHoverAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<TextDocumentPositionParams, Hover?>(Methods.TextDocumentHoverName,
_workspace.CurrentSolution, textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentDocumentSymbolName, UseSingleObjectParameterDeserialization = true)]
public Task<object[]> GetTextDocumentDocumentSymbolsAsync(DocumentSymbolParams documentSymbolParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<DocumentSymbolParams, object[]>(Methods.TextDocumentDocumentSymbolName,
_workspace.CurrentSolution, documentSymbolParams, _clientCapabilities, _clientName, cancellationToken);
documentSymbolParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentFormattingName, UseSingleObjectParameterDeserialization = true)]
public Task<TextEdit[]> GetTextDocumentFormattingAsync(DocumentFormattingParams documentFormattingParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<DocumentFormattingParams, TextEdit[]>(Methods.TextDocumentFormattingName,
_workspace.CurrentSolution, documentFormattingParams, _clientCapabilities, _clientName, cancellationToken);
documentFormattingParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentOnTypeFormattingName, UseSingleObjectParameterDeserialization = true)]
public Task<TextEdit[]> GetTextDocumentFormattingOnTypeAsync(DocumentOnTypeFormattingParams documentOnTypeFormattingParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<DocumentOnTypeFormattingParams, TextEdit[]>(Methods.TextDocumentOnTypeFormattingName,
_workspace.CurrentSolution, documentOnTypeFormattingParams, _clientCapabilities, _clientName, cancellationToken);
documentOnTypeFormattingParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentImplementationName, UseSingleObjectParameterDeserialization = true)]
public Task<LSP.Location[]> GetTextDocumentImplementationsAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<TextDocumentPositionParams, LSP.Location[]>(Methods.TextDocumentImplementationName,
_workspace.CurrentSolution, textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentRangeFormattingName, UseSingleObjectParameterDeserialization = true)]
public Task<TextEdit[]> GetTextDocumentRangeFormattingAsync(DocumentRangeFormattingParams documentRangeFormattingParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<DocumentRangeFormattingParams, TextEdit[]>(Methods.TextDocumentRangeFormattingName,
_workspace.CurrentSolution, documentRangeFormattingParams, _clientCapabilities, _clientName, cancellationToken);
documentRangeFormattingParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.TextDocumentSignatureHelpName, UseSingleObjectParameterDeserialization = true)]
public Task<SignatureHelp> GetTextDocumentSignatureHelpAsync(TextDocumentPositionParams textDocumentPositionParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<TextDocumentPositionParams, SignatureHelp>(Methods.TextDocumentSignatureHelpName,
_workspace.CurrentSolution, textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentPositionParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(Methods.WorkspaceSymbolName, UseSingleObjectParameterDeserialization = true)]
public Task<SymbolInformation[]> GetWorkspaceSymbolsAsync(WorkspaceSymbolParams workspaceSymbolParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<WorkspaceSymbolParams, SymbolInformation[]>(Methods.WorkspaceSymbolName,
_workspace.CurrentSolution, workspaceSymbolParams, _clientCapabilities, _clientName, cancellationToken);
workspaceSymbolParams, _clientCapabilities, _clientName, cancellationToken);
[JsonRpcMethod(MSLSPMethods.ProjectContextsName, UseSingleObjectParameterDeserialization = true)]
public Task<ActiveProjectContexts?> GetProjectContextsAsync(GetTextDocumentWithContextParams textDocumentWithContextParams, CancellationToken cancellationToken)
=> _protocol.ExecuteRequestAsync<GetTextDocumentWithContextParams, ActiveProjectContexts?>(MSLSPMethods.ProjectContextsName,
_workspace.CurrentSolution, textDocumentWithContextParams, _clientCapabilities, _clientName, cancellationToken);
textDocumentWithContextParams, _clientCapabilities, _clientName, cancellationToken);
#pragma warning disable VSTHRD100 // Avoid async void methods
private async void DiagnosticService_DiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
......
......@@ -25,7 +25,9 @@ internal class LiveShareLanguageServerClient : AbstractLanguageServerClient
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, true)]
public LiveShareLanguageServerClient(LanguageServerProtocol languageServerProtocol, VisualStudioWorkspace workspace, IDiagnosticService diagnosticService)
public LiveShareLanguageServerClient(LanguageServerProtocol languageServerProtocol,
VisualStudioWorkspace workspace,
IDiagnosticService diagnosticService)
: base(languageServerProtocol, workspace, diagnosticService, diagnosticsClientName: null)
{
}
......
......@@ -38,7 +38,9 @@ internal class RazorLanguageClient : AbstractLanguageServerClient
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RazorLanguageClient(LanguageServerProtocol languageServerProtocol, VisualStudioWorkspace workspace, IDiagnosticService diagnosticService)
public RazorLanguageClient(LanguageServerProtocol languageServerProtocol,
VisualStudioWorkspace workspace,
IDiagnosticService diagnosticService)
: base(languageServerProtocol, workspace, diagnosticService, ClientName)
{
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageClient
{
[Export(typeof(ILspSolutionProvider)), Shared]
class VisualStudioLspSolutionProvider : ILspSolutionProvider
{
private readonly VisualStudioWorkspace _visualStudioWorkspace;
private readonly MiscellaneousFilesWorkspace _miscellaneousFilesWorkspace;
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualStudioLspSolutionProvider(VisualStudioWorkspace visualStudioWorkspace, MiscellaneousFilesWorkspace miscellaneousFilesWorkspace)
{
_visualStudioWorkspace = visualStudioWorkspace;
_miscellaneousFilesWorkspace = miscellaneousFilesWorkspace;
}
public Solution GetCurrentSolutionForMainWorkspace()
{
return _visualStudioWorkspace.CurrentSolution;
}
public ImmutableArray<Document> GetDocuments(Uri documentUri)
{
// First check the VS workspace for matching documents.
var documents = _visualStudioWorkspace.CurrentSolution.GetDocuments(documentUri);
if (documents.IsEmpty)
{
// If there's none in the VS workspace, then check the misc files workspace.
documents = _miscellaneousFilesWorkspace.CurrentSolution.GetDocuments(documentUri);
}
return documents;
}
}
}
......@@ -28,7 +28,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IRunningDocumentTableEventListener
{
private readonly IMetadataAsSourceFileService _fileTrackingMetadataAsSourceService;
private readonly IVsTextManager _textManager;
private readonly Lazy<IVsTextManager> _lazyTextManager;
private readonly RunningDocumentTableEventTracker _runningDocumentTableEventTracker;
......@@ -60,10 +60,14 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IRunningD
SVsServiceProvider serviceProvider)
: base(visualStudioWorkspace.Services.HostServices, WorkspaceKind.MiscellaneousFiles)
{
_foregroundThreadAffinitization = new ForegroundThreadAffinitizedObject(threadingContext, assertIsForeground: true);
_foregroundThreadAffinitization = new ForegroundThreadAffinitizedObject(threadingContext, assertIsForeground: false);
_fileTrackingMetadataAsSourceService = fileTrackingMetadataAsSourceService;
_textManager = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager));
_lazyTextManager = new Lazy<IVsTextManager>(() =>
{
_foregroundThreadAffinitization.AssertIsForeground();
return (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager));
});
var runningDocumentTable = (IVsRunningDocumentTable)serviceProvider.GetService(typeof(SVsRunningDocumentTable));
_runningDocumentTableEventTracker = new RunningDocumentTableEventTracker(threadingContext, editorAdaptersFactoryService, runningDocumentTable, this);
......@@ -103,7 +107,7 @@ private LanguageInformation TryGetLanguageInformation(string filename)
{
LanguageInformation languageInformation = null;
if (ErrorHandler.Succeeded(_textManager.MapFilenameToLanguageSID(filename, out var fileLanguageGuid)))
if (ErrorHandler.Succeeded(_lazyTextManager.Value.MapFilenameToLanguageSID(filename, out var fileLanguageGuid)))
{
_languageInformationByLanguageGuid.TryGetValue(fileLanguageGuid, out languageInformation);
}
......
......@@ -24,12 +24,19 @@ namespace Microsoft.VisualStudio.LanguageServices.LiveShare
/// </summary>
internal abstract class AbstractClassificationsHandler : ILspRequestHandler<ClassificationParams, object[], Solution>
{
private readonly ILspSolutionProvider _solutionProvider;
protected AbstractClassificationsHandler(ILspSolutionProvider solutionProvider)
{
_solutionProvider = solutionProvider;
}
protected abstract Task AddClassificationsAsync(IClassificationService classificationService, Document document, TextSpan textSpan, List<ClassifiedSpan> spans, CancellationToken cancellationToken);
public async Task<object[]> HandleAsync(ClassificationParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
{
request.TextDocument.Uri = requestContext.ProtocolConverter.FromProtocolUri(request.TextDocument.Uri);
var document = requestContext.Context.GetDocument(request.TextDocument);
var document = _solutionProvider.GetDocument(request.TextDocument);
var classificationService = document?.Project.LanguageServices.GetService<IClassificationService>();
if (document == null || classificationService == null)
......
......@@ -29,15 +29,17 @@ namespace Microsoft.VisualStudio.LanguageServices.LiveShare
internal abstract class AbstractGoToDefinitionWithFindUsagesServiceHandler : ILspRequestHandler<LSP.TextDocumentPositionParams, object, Solution>
{
private readonly IMetadataAsSourceFileService _metadataAsSourceService;
private readonly ILspSolutionProvider _solutionProvider;
public AbstractGoToDefinitionWithFindUsagesServiceHandler(IMetadataAsSourceFileService metadataAsSourceService)
=> this._metadataAsSourceService = metadataAsSourceService;
public AbstractGoToDefinitionWithFindUsagesServiceHandler(IMetadataAsSourceFileService metadataAsSourceService, ILspSolutionProvider solutionProvider)
{
_metadataAsSourceService = metadataAsSourceService;
_solutionProvider = solutionProvider;
}
public async Task<object> HandleAsync(LSP.TextDocumentPositionParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
{
var solution = requestContext.Context;
var document = solution.GetDocument(request.TextDocument);
var document = _solutionProvider.GetDocument(request.TextDocument);
if (document == null)
{
return Array.Empty<LSP.Location>();
......
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.LiveShare.CustomProtocol;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
......@@ -24,6 +25,10 @@ namespace Microsoft.VisualStudio.LanguageServices.LiveShare
/// </summary>
internal class ClassificationsHandler : AbstractClassificationsHandler
{
public ClassificationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
protected override async Task AddClassificationsAsync(IClassificationService classificationService, Document document, TextSpan textSpan, List<ClassifiedSpan> spans, CancellationToken cancellationToken)
=> await classificationService.AddSemanticClassificationsAsync(document, textSpan, spans, cancellationToken).ConfigureAwait(false);
}
......@@ -34,7 +39,7 @@ internal class RoslynClassificationsHandler : ClassificationsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RoslynClassificationsHandler()
public RoslynClassificationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
}
......@@ -44,7 +49,7 @@ internal class CSharpClassificationsHandler : ClassificationsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpClassificationsHandler()
public CSharpClassificationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
}
......@@ -54,7 +59,7 @@ internal class VisualBasicClassificationsHandler : ClassificationsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualBasicClassificationsHandler()
public VisualBasicClassificationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
}
......@@ -64,7 +69,7 @@ internal class TypeScriptClassificationsHandler : ClassificationsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptClassificationsHandler()
public TypeScriptClassificationsHandler(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
}
......
......@@ -5,6 +5,7 @@
using System;
using System.ComponentModel.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.MetadataAsSource;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
......@@ -17,8 +18,8 @@ internal class RoslynGoToDefinitionHandler : AbstractGoToDefinitionWithFindUsage
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RoslynGoToDefinitionHandler([Import(AllowDefault = true)] IMetadataAsSourceFileService metadataAsSourceService)
: base(metadataAsSourceService)
public RoslynGoToDefinitionHandler([Import(AllowDefault = true)] IMetadataAsSourceFileService metadataAsSourceService,
ILspSolutionProvider solutionProvider) : base(metadataAsSourceService, solutionProvider)
{
}
}
......@@ -28,7 +29,7 @@ internal class TypeScriptGoToDefinitionHandler : AbstractGoToDefinitionWithFindU
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptGoToDefinitionHandler() : base(null)
public TypeScriptGoToDefinitionHandler(ILspSolutionProvider solutionProvider) : base(null, solutionProvider)
{
}
}
......
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.VisualStudio.LanguageServices.LiveShare.CustomProtocol;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
......@@ -18,7 +19,8 @@ internal class RoslynPreviewCodeActionsHandler : PreviewCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RoslynPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public RoslynPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
: base(codeFixService, codeRefactoringService, solutionProvider)
{
}
}
......@@ -28,7 +30,8 @@ internal class CSharpPreviewCodeActionsHandler : PreviewCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public CSharpPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
: base(codeFixService, codeRefactoringService, solutionProvider)
{
}
}
......@@ -38,7 +41,8 @@ internal class VisualBasicPreviewCodeActionsHandler : PreviewCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualBasicPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public VisualBasicPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
: base(codeFixService, codeRefactoringService, solutionProvider)
{
}
}
......@@ -48,7 +52,8 @@ internal class TypeScriptPreviewCodeActionsHandler : PreviewCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public TypeScriptPreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
: base(codeFixService, codeRefactoringService, solutionProvider)
{
}
}
......
......@@ -13,26 +13,34 @@
using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.VisualStudio.LanguageServices.LiveShare
{
internal class PreviewCodeActionsHandler : CodeActionsHandlerBase, ILspRequestHandler<RunCodeActionParams, LSP.TextEdit[], Solution>
internal class PreviewCodeActionsHandler : ILspRequestHandler<RunCodeActionParams, LSP.TextEdit[], Solution>
{
public PreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService)
private readonly ICodeFixService _codeFixService;
private readonly ICodeRefactoringService _codeRefactoringService;
private readonly ILspSolutionProvider _solutionProvider;
public PreviewCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider)
{
_codeFixService = codeFixService;
_codeRefactoringService = codeRefactoringService;
_solutionProvider = solutionProvider;
}
public async Task<LSP.TextEdit[]> HandleAsync(RunCodeActionParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
{
var edits = ArrayBuilder<LSP.TextEdit>.GetInstance();
var solution = requestContext.Context;
var codeActions = await GetCodeActionsAsync(solution,
request.CodeActionParams.TextDocument,
var document = _solutionProvider.GetDocument(request.CodeActionParams.TextDocument);
var codeActions = await CodeActionsHandler.GetCodeActionsAsync(document,
_codeFixService,
_codeRefactoringService,
request.CodeActionParams.Range,
null, cancellationToken).ConfigureAwait(false);
cancellationToken).ConfigureAwait(false);
var actionToRun = codeActions?.FirstOrDefault(a => a.Title == request.Title);
......@@ -41,7 +49,6 @@ public async Task<LSP.TextEdit[]> HandleAsync(RunCodeActionParams request, Reque
var operations = await actionToRun.GetOperationsAsync(cancellationToken).ConfigureAwait(false);
var applyChangesOperation = operations.OfType<ApplyChangesOperation>().FirstOrDefault();
var document = solution.GetDocument(request.CodeActionParams.TextDocument);
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
if (applyChangesOperation != null && document != null)
......
......@@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.LanguageServer.CustomProtocol;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
......@@ -25,13 +26,18 @@ namespace Microsoft.VisualStudio.LanguageServices.LiveShare
/// Run code actions handler. Called when lightbulb invoked.
/// Code actions must be applied from the UI thread in VS.
/// </summary>
internal abstract class RunCodeActionsHandler : CodeActionsHandlerBase, ILspRequestHandler<LSP.ExecuteCommandParams, object, Solution>
internal abstract class RunCodeActionsHandler : ILspRequestHandler<LSP.ExecuteCommandParams, object, Solution>
{
private readonly ICodeFixService _codeFixService;
private readonly ICodeRefactoringService _codeRefactoringService;
private readonly ILspSolutionProvider _solutionProvider;
private readonly IThreadingContext _threadingContext;
protected RunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IThreadingContext threadingContext)
: base(codeFixService, codeRefactoringService)
protected RunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, ILspSolutionProvider solutionProvider, IThreadingContext threadingContext)
{
_codeFixService = codeFixService;
_codeRefactoringService = codeRefactoringService;
_solutionProvider = solutionProvider;
_threadingContext = threadingContext;
}
......@@ -45,13 +51,12 @@ public async Task<object> HandleAsync(LSP.ExecuteCommandParams request, RequestC
request.Arguments = command.Arguments;
}
if (request.Command == RunCodeActionCommandName)
if (request.Command == CodeActionsHandler.RunCodeActionCommandName)
{
var runRequest = ((JToken)request.Arguments.Single()).ToObject<RunCodeActionParams>();
var codeActions = await GetCodeActionsAsync(requestContext.Context,
runRequest.CodeActionParams.TextDocument,
runRequest.CodeActionParams.Range,
null, cancellationToken).ConfigureAwait(false);
var document = _solutionProvider.GetDocument(runRequest.CodeActionParams.TextDocument);
var codeActions = await CodeActionsHandler.GetCodeActionsAsync(document, _codeFixService, _codeRefactoringService,
runRequest.CodeActionParams.Range, cancellationToken).ConfigureAwait(false);
var actionToRun = codeActions?.FirstOrDefault(a => a.Title == runRequest.Title);
......@@ -62,7 +67,7 @@ public async Task<object> HandleAsync(LSP.ExecuteCommandParams request, RequestC
// TODO - This UI thread dependency should be removed.
// https://github.com/dotnet/roslyn/projects/45#card-20619668
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
operation.Apply(requestContext.Context.Workspace, cancellationToken);
operation.Apply(document.Project.Solution.Workspace, cancellationToken);
}
}
......@@ -87,7 +92,8 @@ internal class RoslynRunCodeActionsHandler : RunCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RoslynRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, threadingContext)
public RoslynRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService,
ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, solutionProvider, threadingContext)
{
}
}
......@@ -97,7 +103,8 @@ internal class CSharpRunCodeActionsHandler : RunCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, threadingContext)
public CSharpRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService,
ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, solutionProvider, threadingContext)
{
}
}
......@@ -107,7 +114,8 @@ internal class VisualBasicRunCodeActionsHandler : RunCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualBasicRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, threadingContext)
public VisualBasicRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService,
ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, solutionProvider, threadingContext)
{
}
}
......@@ -117,7 +125,8 @@ internal class TypeScriptRunCodeActionsHandler : RunCodeActionsHandler
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, threadingContext)
public TypeScriptRunCodeActionsHandler(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService,
ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(codeFixService, codeRefactoringService, solutionProvider, threadingContext)
{
}
}
......
......@@ -17,6 +17,7 @@
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServices.LiveShare.Protocol;
using Microsoft.VisualStudio.LiveShare.LanguageServices;
using Microsoft.CodeAnalysis.LanguageServer;
namespace Microsoft.VisualStudio.LanguageServices.LiveShare
{
......@@ -26,7 +27,8 @@ internal abstract class CodeActionsHandlerShim : CodeActionsHandler, ILspRequest
protected const string ProviderName = "Roslyn";
[Obsolete(MefConstruction.ImportingConstructorMessage, true)]
public CodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService) : base(codeFixService, codeRefactoringService)
public CodeActionsHandlerShim(ILspSolutionProvider solutionProvider, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService, solutionProvider)
{
}
......@@ -45,7 +47,7 @@ public CodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringSe
/// <returns></returns>
public async Task<SumType<Command, CodeAction>[]> HandleAsync(CodeActionParams param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
{
var result = await base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken).ConfigureAwait(false);
var result = await base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken).ConfigureAwait(false);
var commands = new ArrayBuilder<SumType<Command, CodeAction>>();
foreach (var resultObj in result)
......@@ -71,8 +73,8 @@ internal class RoslynCodeActionsHandlerShim : CodeActionsHandlerShim
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public RoslynCodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService)
public RoslynCodeActionsHandlerShim(ILspSolutionProvider solutionProvider, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(solutionProvider, codeFixService, codeRefactoringService)
{
}
}
......@@ -82,8 +84,8 @@ internal class CSharpCodeActionsHandlerShim : CodeActionsHandlerShim
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpCodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService)
public CSharpCodeActionsHandlerShim(ILspSolutionProvider solutionProvider, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(solutionProvider, codeFixService, codeRefactoringService)
{
}
}
......@@ -93,8 +95,8 @@ internal class VisualBasicCodeActionsHandlerShim : CodeActionsHandlerShim
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public VisualBasicCodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService)
public VisualBasicCodeActionsHandlerShim(ILspSolutionProvider solutionProvider, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(solutionProvider, codeFixService, codeRefactoringService)
{
}
}
......@@ -104,8 +106,8 @@ internal class TypeScriptCodeActionsHandlerShim : CodeActionsHandlerShim
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptCodeActionsHandlerShim(ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(codeFixService, codeRefactoringService)
public TypeScriptCodeActionsHandlerShim(ILspSolutionProvider solutionProvider, ICodeFixService codeFixService, ICodeRefactoringService codeRefactoringService)
: base(solutionProvider, codeFixService, codeRefactoringService)
{
}
}
......
......@@ -17,6 +17,7 @@
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.SignatureHelp;
using Microsoft.CodeAnalysis.Text;
......@@ -33,7 +34,6 @@ namespace Microsoft.VisualStudio.LanguageServices.LiveShare
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.TextDocumentCompletionName)]
internal class TypeScriptCompletionHandlerShim : CompletionHandler, ILspRequestHandler<object, LanguageServer.Protocol.CompletionItem[], Solution>
{
/// <summary>
/// The VS LSP client supports streaming using IProgress on various requests.
/// However, this works through liveshare on the LSP client, but not the LSP extension.
......@@ -52,7 +52,7 @@ internal class TypeScriptCompletionHandlerShim : CompletionHandler, ILspRequestH
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptCompletionHandlerShim()
public TypeScriptCompletionHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
......@@ -62,7 +62,7 @@ public Task<LanguageServer.Protocol.CompletionItem[]> HandleAsync(object input,
// However, this works through liveshare on the LSP client, but not the LSP extension.
// see https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1107682 for tracking.
var request = ((JObject)input).ToObject<CompletionParams>(s_jsonSerializer);
return base.HandleRequestAsync(requestContext.Context, request, requestContext.GetClientCapabilities(), null, cancellationToken);
return base.HandleRequestAsync(request, requestContext.GetClientCapabilities(), null, cancellationToken);
}
}
......@@ -71,12 +71,12 @@ internal class TypeScriptCompletionResolverHandlerShim : CompletionResolveHandle
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptCompletionResolverHandlerShim()
public TypeScriptCompletionResolverHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public Task<LanguageServer.Protocol.CompletionItem> HandleAsync(LanguageServer.Protocol.CompletionItem param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken);
}
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.TextDocumentDocumentHighlightName)]
......@@ -84,12 +84,12 @@ internal class TypeScriptDocumentHighlightHandlerShim : DocumentHighlightsHandle
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptDocumentHighlightHandlerShim()
public TypeScriptDocumentHighlightHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public Task<DocumentHighlight[]> HandleAsync(TextDocumentPositionParams param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken);
}
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.TextDocumentDocumentSymbolName)]
......@@ -97,7 +97,7 @@ internal class TypeScriptDocumentSymbolsHandlerShim : DocumentSymbolsHandler, IL
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptDocumentSymbolsHandlerShim()
public TypeScriptDocumentSymbolsHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
......@@ -110,7 +110,7 @@ public async Task<SymbolInformation[]> HandleAsync(DocumentSymbolParams param, R
clientCapabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = false;
}
var response = await base.HandleRequestAsync(requestContext.Context, param, clientCapabilities, null, cancellationToken).ConfigureAwait(false);
var response = await base.HandleRequestAsync(param, clientCapabilities, null, cancellationToken).ConfigureAwait(false);
// Since hierarchicalSupport will never be true, it is safe to cast the response to SymbolInformation[]
return response.Cast<SymbolInformation>().ToArray();
......@@ -124,11 +124,11 @@ internal class TypeScriptFormatDocumentHandlerShim : FormatDocumentHandler, ILsp
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptFormatDocumentHandlerShim(IThreadingContext threadingContext)
public TypeScriptFormatDocumentHandlerShim(ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(solutionProvider)
=> _threadingContext = threadingContext;
public Task<TextEdit[]> HandleAsync(DocumentFormattingParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, request, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(request, requestContext.GetClientCapabilities(), null, cancellationToken);
protected override async Task<IList<TextChange>> GetFormattingChangesAsync(IEditorFormattingService formattingService, Document document, TextSpan? textSpan, CancellationToken cancellationToken)
{
......@@ -145,11 +145,11 @@ internal class TypeScriptFormatDocumentRangeHandlerShim : FormatDocumentRangeHan
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptFormatDocumentRangeHandlerShim(IThreadingContext threadingContext)
public TypeScriptFormatDocumentRangeHandlerShim(ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(solutionProvider)
=> _threadingContext = threadingContext;
public Task<TextEdit[]> HandleAsync(DocumentRangeFormattingParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, request, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(request, requestContext.GetClientCapabilities(), null, cancellationToken);
protected override async Task<IList<TextChange>> GetFormattingChangesAsync(IEditorFormattingService formattingService, Document document, TextSpan? textSpan, CancellationToken cancellationToken)
{
......@@ -166,11 +166,11 @@ internal class TypeScriptFormatDocumentOnTypeHandlerShim : FormatDocumentOnTypeH
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptFormatDocumentOnTypeHandlerShim(IThreadingContext threadingContext)
public TypeScriptFormatDocumentOnTypeHandlerShim(ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(solutionProvider)
=> _threadingContext = threadingContext;
public Task<TextEdit[]> HandleAsync(DocumentOnTypeFormattingParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, request, requestContext?.ClientCapabilities?.ToObject<ClientCapabilities>(), null, cancellationToken);
=> base.HandleRequestAsync(request, requestContext?.ClientCapabilities?.ToObject<ClientCapabilities>(), null, cancellationToken);
protected override async Task<IList<TextChange>?> GetFormattingChangesAsync(IEditorFormattingService formattingService, Document document, char typedChar, int position, CancellationToken cancellationToken)
{
......@@ -194,11 +194,11 @@ internal class TypeScriptFindImplementationsHandlerShim : FindImplementationsHan
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptFindImplementationsHandlerShim(IThreadingContext threadingContext)
public TypeScriptFindImplementationsHandlerShim(ILspSolutionProvider solutionProvider, IThreadingContext threadingContext) : base(solutionProvider)
=> _threadingContext = threadingContext;
public Task<LanguageServer.Protocol.Location[]> HandleAsync(TextDocumentPositionParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, request, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(request, requestContext.GetClientCapabilities(), null, cancellationToken);
protected override async Task FindImplementationsAsync(IFindUsagesService findUsagesService, Document document, int position, SimpleFindUsagesContext context)
{
......@@ -213,13 +213,14 @@ internal class TypeScriptInitializeHandlerShim : InitializeHandler, ILspRequestH
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptInitializeHandlerShim([ImportMany] IEnumerable<Lazy<CompletionProvider, CompletionProviderMetadata>> completionProviders) : base(completionProviders)
public TypeScriptInitializeHandlerShim([ImportMany] IEnumerable<Lazy<CompletionProvider, CompletionProviderMetadata>> completionProviders,
ILspSolutionProvider solutionProvider) : base(completionProviders)
{
}
public async Task<InitializeResult> HandleAsync(InitializeParams param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
{
var initializeResult = await base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken).ConfigureAwait(false);
var initializeResult = await base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken).ConfigureAwait(false);
initializeResult.Capabilities.Experimental = new RoslynExperimentalCapabilities { SyntacticLspProvider = true };
return initializeResult;
}
......@@ -230,12 +231,13 @@ internal class TypeScriptSignatureHelpHandlerShim : SignatureHelpHandler, ILspRe
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptSignatureHelpHandlerShim([ImportMany] IEnumerable<Lazy<ISignatureHelpProvider, OrderableLanguageMetadata>> allProviders) : base(allProviders)
public TypeScriptSignatureHelpHandlerShim([ImportMany] IEnumerable<Lazy<ISignatureHelpProvider, OrderableLanguageMetadata>> allProviders,
ILspSolutionProvider solutionProvider) : base(allProviders, solutionProvider)
{
}
public Task<SignatureHelp> HandleAsync(TextDocumentPositionParams param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken);
}
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.TextDocumentRenameName)]
......@@ -243,12 +245,12 @@ internal class TypeScriptRenameHandlerShim : RenameHandler, ILspRequestHandler<R
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptRenameHandlerShim()
public TypeScriptRenameHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
public Task<WorkspaceEdit?> HandleAsync(RenameParams param, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, param, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(param, requestContext.GetClientCapabilities(), null, cancellationToken);
}
[ExportLspRequestHandler(LiveShareConstants.TypeScriptContractName, Methods.WorkspaceSymbolName)]
......@@ -256,12 +258,12 @@ internal class TypeScriptWorkspaceSymbolsHandlerShim : WorkspaceSymbolsHandler,
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public TypeScriptWorkspaceSymbolsHandlerShim()
public TypeScriptWorkspaceSymbolsHandlerShim(ILspSolutionProvider solutionProvider) : base(solutionProvider)
{
}
[JsonRpcMethod(UseSingleObjectParameterDeserialization = true)]
public Task<SymbolInformation[]> HandleAsync(WorkspaceSymbolParams request, RequestContext<Solution> requestContext, CancellationToken cancellationToken)
=> base.HandleRequestAsync(requestContext.Context, request, requestContext.GetClientCapabilities(), null, cancellationToken);
=> base.HandleRequestAsync(request, requestContext.GetClientCapabilities(), null, cancellationToken);
}
}
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.LanguageServer.Handler.Commands;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Composition;
......@@ -59,7 +60,8 @@ protected override ExportProvider GetExportProvider()
.WithPart(typeof(MockDocumentNavigationServiceFactory))
.WithParts(liveShareRequestHelperTypes)
.WithParts(roslynRequestHelperTypes)
.WithParts(executeCommandHandlerTypes));
.WithParts(executeCommandHandlerTypes)
.WithPart(typeof(TestLspSolutionProvider)));
return exportProviderFactory.CreateExportProvider();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册