-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Multi-target LSP tests to run against .NET #77173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c53e1e0
c3fc118
9cfab2d
26317e4
76b364e
3f873ed
32a5390
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,33 +3,39 @@ | |
| // See the LICENSE file in the project root for more information. | ||
|
|
||
| using System; | ||
| using System.Collections.Immutable; | ||
| using System.Collections.Generic; | ||
| using System.Composition; | ||
| using System.IO; | ||
| using System.Linq; | ||
| using System.ServiceModel.Syndication; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
| using System.Xml.Linq; | ||
| using Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript; | ||
| using Microsoft.CodeAnalysis.ExternalAccess.VSTypeScript.Api; | ||
| using Microsoft.CodeAnalysis.Host.Mef; | ||
| using Microsoft.CodeAnalysis.LanguageServer; | ||
| using Microsoft.CodeAnalysis.Simplification; | ||
| using Microsoft.CodeAnalysis.Test.Utilities; | ||
| using Roslyn.LanguageServer.Protocol; | ||
| using Microsoft.CommonLanguageServerProtocol.Framework; | ||
| using Nerdbank.Streams; | ||
| using Roslyn.LanguageServer.Protocol; | ||
| using Roslyn.Test.Utilities; | ||
| using StreamJsonRpc; | ||
| using Xunit; | ||
| using Xunit.Abstractions; | ||
|
|
||
| namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests; | ||
| namespace Microsoft.CodeAnalysis.Editor.UnitTests.LanguageServer; | ||
|
|
||
| public class VSTypeScriptHandlerTests : AbstractLanguageServerProtocolTests | ||
| { | ||
| public VSTypeScriptHandlerTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) | ||
| { | ||
| } | ||
|
|
||
| protected override TestComposition Composition => base.Composition.AddParts(typeof(TypeScriptHandlerFactory)); | ||
| protected override TestComposition Composition => EditorTestCompositions.LanguageServerProtocolEditorFeatures | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. requires Editor features here as the VS typescript EA components live in editor features. |
||
| .AddParts(typeof(TypeScriptHandlerFactory)) | ||
| .AddParts(typeof(TestWorkspaceRegistrationService)); | ||
|
|
||
| [Fact] | ||
| public async Task TestExternalAccessTypeScriptHandlerInvoked() | ||
|
|
@@ -88,43 +94,50 @@ public async Task TestGetSimplifierOptionsOnTypeScriptDocument() | |
| Assert.Same(SimplifierOptions.CommonDefaults, simplifierOptions); | ||
| } | ||
|
|
||
| private async Task<TestLspServer> CreateTsTestLspServerAsync(string workspaceXml, InitializationOptions? options = null) | ||
| private async Task<VSTypeScriptTestLspServer> CreateTsTestLspServerAsync(string workspaceXml, InitializationOptions? options = null) | ||
| { | ||
| var (clientStream, serverStream) = FullDuplexStream.CreatePair(); | ||
|
|
||
| var testWorkspace = CreateWorkspace(options, mutatingLspWorkspace: false, workspaceKind: null); | ||
| testWorkspace.InitializeDocuments(XElement.Parse(workspaceXml), openDocuments: false); | ||
|
|
||
| // Ensure workspace operations are completed so we don't get unexpected workspace changes while running. | ||
| await WaitForWorkspaceOperationsAsync(testWorkspace); | ||
| var languageServerTarget = CreateLanguageServer(serverStream, serverStream, testWorkspace); | ||
|
|
||
| return await TestLspServer.CreateAsync(testWorkspace, new ClientCapabilities(), languageServerTarget, clientStream); | ||
| return await VSTypeScriptTestLspServer.CreateAsync(testWorkspace, new InitializationOptions(), TestOutputLspLogger); | ||
| } | ||
|
|
||
| private static RoslynLanguageServer CreateLanguageServer(Stream inputStream, Stream outputStream, EditorTestWorkspace workspace) | ||
| private class VSTypeScriptTestLspServer : AbstractTestLspServer<LspTestWorkspace, TestHostDocument, TestHostProject, TestHostSolution> | ||
| { | ||
| var capabilitiesProvider = workspace.ExportProvider.GetExportedValue<ExperimentalCapabilitiesProvider>(); | ||
| var servicesProvider = workspace.ExportProvider.GetExportedValue<VSTypeScriptLspServiceProvider>(); | ||
|
|
||
| var messageFormatter = RoslynLanguageServer.CreateJsonMessageFormatter(); | ||
| var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, messageFormatter)) | ||
| public VSTypeScriptTestLspServer(LspTestWorkspace testWorkspace, Dictionary<string, IList<Roslyn.LanguageServer.Protocol.Location>> locations, InitializationOptions options, AbstractLspLogger logger) : base(testWorkspace, locations, options, logger) | ||
| { | ||
| ExceptionStrategy = ExceptionProcessing.ISerializable, | ||
| }; | ||
|
|
||
| var logger = NoOpLspLogger.Instance; | ||
| } | ||
|
|
||
| var languageServer = new RoslynLanguageServer( | ||
| servicesProvider, jsonRpc, messageFormatter.JsonSerializerOptions, | ||
| capabilitiesProvider, | ||
| logger, | ||
| workspace.Services.HostServices, | ||
| [InternalLanguageNames.TypeScript], | ||
| WellKnownLspServerKinds.RoslynTypeScriptLspServer); | ||
| protected override RoslynLanguageServer CreateLanguageServer(Stream inputStream, Stream outputStream, WellKnownLspServerKinds serverKind, AbstractLspLogger logger) | ||
| { | ||
| var capabilitiesProvider = TestWorkspace.ExportProvider.GetExportedValue<ExperimentalCapabilitiesProvider>(); | ||
| var servicesProvider = TestWorkspace.ExportProvider.GetExportedValue<VSTypeScriptLspServiceProvider>(); | ||
|
|
||
| var messageFormatter = RoslynLanguageServer.CreateJsonMessageFormatter(); | ||
| var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, messageFormatter)) | ||
| { | ||
| ExceptionStrategy = ExceptionProcessing.ISerializable, | ||
| }; | ||
|
|
||
| var languageServer = new RoslynLanguageServer( | ||
| servicesProvider, jsonRpc, messageFormatter.JsonSerializerOptions, | ||
| capabilitiesProvider, | ||
| logger, | ||
| TestWorkspace.Services.HostServices, | ||
| [InternalLanguageNames.TypeScript], | ||
| WellKnownLspServerKinds.RoslynTypeScriptLspServer); | ||
|
|
||
| jsonRpc.StartListening(); | ||
| return languageServer; | ||
| } | ||
|
|
||
| jsonRpc.StartListening(); | ||
| return languageServer; | ||
| public static async Task<VSTypeScriptTestLspServer> CreateAsync(LspTestWorkspace testWorkspace, InitializationOptions options, AbstractLspLogger logger) | ||
| { | ||
| var locations = await GetAnnotatedLocationsAsync(testWorkspace, testWorkspace.CurrentSolution); | ||
| var server = new VSTypeScriptTestLspServer(testWorkspace, locations, options, logger); | ||
| await server.InitializeAsync(); | ||
| return server; | ||
| } | ||
| } | ||
|
|
||
| internal record TSRequest(Uri Document, string Project); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,44 +31,26 @@ | |
|
|
||
| namespace Microsoft.CodeAnalysis.Test.Utilities; | ||
|
|
||
| public partial class EditorTestWorkspace : TestWorkspace<EditorTestHostDocument, EditorTestHostProject, EditorTestHostSolution>, ILspWorkspace | ||
| public partial class EditorTestWorkspace : TestWorkspace<EditorTestHostDocument, EditorTestHostProject, EditorTestHostSolution> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we're not using this anymore for any LSP tests that require mutation, so no need for it to implement the LSP mutation methods. Only used by doc outline tests at the moment (which work with any workspace). |
||
| { | ||
| private const string ReferencesOnDiskAttributeName = "ReferencesOnDisk"; | ||
|
|
||
| private readonly Dictionary<string, ITextBuffer2> _createdTextBuffers = []; | ||
| private readonly bool _supportsLspMutation; | ||
|
|
||
| internal EditorTestWorkspace( | ||
| TestComposition? composition = null, | ||
| string? workspaceKind = WorkspaceKind.Host, | ||
| Guid solutionTelemetryId = default, | ||
| bool disablePartialSolutions = true, | ||
| bool ignoreUnchangeableDocumentsWhenApplyingChanges = true, | ||
| WorkspaceConfigurationOptions? configurationOptions = null, | ||
| bool supportsLspMutation = false) | ||
| WorkspaceConfigurationOptions? configurationOptions = null) | ||
| : base(composition ?? EditorTestCompositions.EditorFeatures, | ||
| workspaceKind, | ||
| solutionTelemetryId, | ||
| disablePartialSolutions, | ||
| ignoreUnchangeableDocumentsWhenApplyingChanges, | ||
| configurationOptions) | ||
| { | ||
| _supportsLspMutation = supportsLspMutation; | ||
| } | ||
|
|
||
| bool ILspWorkspace.SupportsMutation => _supportsLspMutation; | ||
|
|
||
| ValueTask ILspWorkspace.UpdateTextIfPresentAsync(DocumentId documentId, SourceText sourceText, CancellationToken cancellationToken) | ||
| { | ||
| Contract.ThrowIfFalse(_supportsLspMutation); | ||
| OnDocumentTextChanged(documentId, sourceText, PreservationMode.PreserveIdentity, requireDocumentPresent: false); | ||
| return ValueTaskFactory.CompletedTask; | ||
| } | ||
|
|
||
| internal override ValueTask TryOnDocumentClosedAsync(DocumentId documentId, CancellationToken cancellationToken) | ||
| { | ||
| Contract.ThrowIfFalse(_supportsLspMutation); | ||
| return base.TryOnDocumentClosedAsync(documentId, cancellationToken); | ||
| } | ||
|
|
||
| private protected override EditorTestHostDocument CreateDocument( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.