Skip to content

Conversation

@dibarbet
Copy link
Member

@dibarbet dibarbet commented Feb 12, 2025

Previously, all LSP tests ran against net472 only, even though the LSP code running in VSCode ran against .NET9. So we've had a test gap here for a while.

But some refactorings Tomas did a couple weeks ago to TestWorkspace now make it relatively straightforward to multi-target these tests. This gets us both CI coverage on .NET core as well as the ability to debug these tests using VSCode (it only ships with a .net core debugger).

The changes in the PR fit a few categories

  1. Removing EditorFeatures dependencies from the Protocol unit tests. This generally resulted in removing usages of EditorTestWorkspace and text buffers. Text buffers were previously mostly used as a proxy for opening a file in the workspace, and didn't actually require text buffers.
  2. Fixing new nullable warnings that came from bumping the tfm
  3. Refactoring the TestLspServer type a little bit to allow either the LspTestWorkspace or EditorTestWorkspace (for tests in EditorFeatures that require text buffers, like the document outline tests).

CI:
image

@ghost ghost added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Feb 12, 2025
@dibarbet dibarbet changed the title Multi-target LSP tests to run against .NET9 Multi-target LSP tests to run against .NET Feb 12, 2025
namespace Microsoft.CodeAnalysis.Test.Utilities;

public partial class EditorTestWorkspace : TestWorkspace<EditorTestHostDocument, EditorTestHostProject, EditorTestHostSolution>, ILspWorkspace
public partial class EditorTestWorkspace : TestWorkspace<EditorTestHostDocument, EditorTestHostProject, EditorTestHostSolution>
Copy link
Member Author

Choose a reason for hiding this comment

The 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).

}

protected virtual TestComposition Composition => EditorFeaturesLspComposition;
protected virtual TestComposition Composition => FeaturesLspComposition;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we generally don't need editorfeatures in the composition anymore. Previously it was required to test LSP APIs that returned internal VS types - we would have a default service in the protocol layer, and override it in editor features (to return things like classified text runs).

However now we have all our own types and the conversions are in the protocol layer too, so this is generally not necessary.

/// This ensures that events like workspace registration / workspace changes are processed by the time we exit this method.
/// </summary>
protected static async Task WaitForWorkspaceOperationsAsync(EditorTestWorkspace workspace)
protected static async Task WaitForWorkspaceOperationsAsync<TDocument, TProject, TSolution>(TestWorkspace<TDocument, TProject, TSolution> workspace)
Copy link
Member Author

@dibarbet dibarbet Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generics are required so this can be passed an EditorTestWorkspace (for a few tests in higher layers that use that) or LspTestWorkspace (almost everything else).

}
}

internal abstract class AbstractTestLspServer<TWorkspace, TDocument, TProject, TSolution> : IAsyncDisposable
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactored TestLspServer a bit so it can be passed any implementation of TestWorkspace<TDocument, TProject, TSolution>. mostly this is just the LspTestWorkspace, but as above there are a few cases where we still use EditorTestWorkspace.

/// Opens a document in the workspace only, and waits for workspace operations.
/// Use <see cref="OpenDocumentAsync(Uri, string, string)"/> if the document should be opened in LSP"/>
/// </summary>
public async Task OpenDocumentInWorkspaceAsync(DocumentId documentId, bool openAllLinkedDocuments, SourceText? text = null)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previously, some tests opened text buffers to simulate opening a file in the workspace (and setting things like active document context).

We don't actually need the buffers - instead we can just open the documents in the workspace directly.

var originalText = await testLspServer.GetDocumentTextAsync(textDocumentEdit[0].TextDocument.Uri);
var edits = textDocumentEdit[0].Edits.Select(e => (LSP.TextEdit)e.Value).ToArray();
var updatedText = ApplyTextEdits(edits, originalText);
Assert.Equal(expectedText, updatedText);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The text edits for this test changed slightly when we switched to LspTestWorkspace because the source texts were no longer backed by the text buffer source text implementation. Instead of updating the hardcoded edits, much cleaner to apply the edits and verify the end result.


Assert.Equal("CS1513", results.Single().Diagnostics.Single().Code);
Assert.NotNull(results.Single().Diagnostics.Single().CodeDescription!.Href);
Assert.Equal("CS1513", results.Single().Diagnostics!.Single().Code);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

everything in this file is removal of the text buffer calls and nullable updates

return server;
}

internal class EditorTestLspServer : AbstractTestLspServer<EditorTestWorkspace, EditorTestHostDocument, EditorTestHostProject, EditorTestHostSolution>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are the tests that still require the EditorTestWorkspace because they deal with text buffers in the tests.

}

protected override TestComposition Composition => base.Composition.AddParts(typeof(TypeScriptHandlerFactory));
protected override TestComposition Composition => EditorTestCompositions.LanguageServerProtocolEditorFeatures
Copy link
Member Author

Choose a reason for hiding this comment

The 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.

@dibarbet dibarbet marked this pull request as ready for review February 13, 2025 01:25
@dibarbet dibarbet requested a review from a team as a code owner February 13, 2025 01:25
…s.cs

Co-authored-by: Joey Robichaud <jorobich@microsoft.com>
@dibarbet dibarbet merged commit 9dd780c into dotnet:main Feb 13, 2025
25 checks passed
@dibarbet dibarbet deleted the lsp_net_tests branch February 13, 2025 18:50
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead VSCode

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants