Skip to content
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

Add feature flag to allow VS to use the LSP based editor #49996

Merged
merged 32 commits into from
Mar 3, 2021

Conversation

dibarbet
Copy link
Member

@dibarbet dibarbet commented Dec 16, 2020

Adds a feature flag to use the LSP editor for C#/VB in local scenarios. This flag is only shown in the preview features menu in int.main and int.preview.
csharp_lsp

Additionally, adds test infrastructure for running LSP tests

@@ -108,7 +109,8 @@ private static bool CanRename(RenameCommandArgs args)
{
return args.SubjectBuffer.TryGetWorkspace(out var workspace) &&
workspace.CanApplyChange(ApplyChangesKind.ChangeDocument) &&
args.SubjectBuffer.SupportsRename();
args.SubjectBuffer.SupportsRename() &&
!workspace.Services.GetService<IWorkspaceContextService>().IsInLspEditorContext();
Copy link
Member

Choose a reason for hiding this comment

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

i dislike this. why is this not part of the .SupportsRename extension? seems weird for the buffer to say it supports this and we then override.

Copy link
Member

Choose a reason for hiding this comment

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

put another way, i highly dislike this sort of sprinkling aruond of a different concept that features should not have to care about.

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi this is ready for review now - I moved this to the supports rename, but in general I agree and don't really like sprinkling this around either, but I'm not sure I have a better idea.

Basically I need to disable the legacy editor entry points when running under the LSP editor for features that are provided by LSP (e.g. rename) but need to keep other editor entry points active (e.g. syntax classifications).

I was potentially considering perhaps modifying the extension methods to convert textbuffer/snapshot to documents (GetOpenDocumentInCurrentContextWithChanges) to return nothing when under LSP mode, but then I'd still need a separate method to allow some features to retrieve documents from the buffer (e.g. syntax classification)

Copy link
Member Author

Choose a reason for hiding this comment

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

@CyrusNajmabadi I've gotten these new integration tests working again and am looking to get this in, so wanted to followup on this conversation. Can discuss offline whenever you have a meeting free day :)

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

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

basicaly, i don't understand what's goign on here. i have no intuition for when/how/why we need to sprinkle this stuff around.

@dibarbet dibarbet force-pushed the local_lsp branch 2 times, most recently from be6dc7b to 2cda1db Compare January 15, 2021 03:08
@@ -372,6 +373,13 @@ function TestUsingRunTests() {
$args += " --sequential"
$args += " --include '\.IntegrationTests'"
$args += " --include 'Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests'"

if ($lspEditor) {
$args += " --testfilter FullyQualifiedName~Roslyn.VisualStudio.IntegrationTests.LanguageServerProtocol|Editor=LanguageServerProtocol"
Copy link
Member Author

Choose a reason for hiding this comment

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

I went with both a separate namespace and additional trait name to enable multiple testing scenarios:

  1. Running selected existing integration tests under the LSP editor (uses trait to select which tests).
  2. Writing LSP only integration tests (uses separate namespace).
  3. Ensure that the tests in 2) do not run in normal integration test runs.

Copy link
Member

@jasonmalinowski jasonmalinowski Mar 2, 2021

Choose a reason for hiding this comment

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

I guess the trait is sufficient right, if you just put the trait on containing types? My strong worry about the magic namespace is that we might rename or move something and not realize that tests aren't running anymore. Having the single method with the trait makes it a bit easier to know everything either works or doesn't.

Copy link
Member

Choose a reason for hiding this comment

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

(see other comment though that the only test currently in it's own namespace I think is better just combined with the existing test which checks if it's in LSP mode or not...)

Copy link
Member

Choose a reason for hiding this comment

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

And yes, we once had an integration test CI that was passing because whatever glob was looking for assemblies to run wasn't updated, and so it was running nothing. That was a "fun" discovery.

Copy link
Member Author

Choose a reason for hiding this comment

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

@jasonmalinowski If we ever want to support running a test in LSP only context then we must have a separate namespace or something similar. Otherwise I have no way to filter out LSP-only tests from the normal run (since the normal run includes shared tests with the LSP trait).

I can guarantee that there will be LSP only tests, if not gotodef then completion or another feature. I think even for the gotodef test you mention I must have an LSP version and a non-LSP version, even if I share most of the code as they have different input data (window caption).

Copy link
Member

Choose a reason for hiding this comment

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

I guess as long as we're using environment variables to control this, there's no reason you can just haven't a ConditionalFact that only runs if the environment variable is set. You can also have the test just check the environment variable in a test if you need to change a string.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah! Today I learned about conditional facts. Ok, I'll use that in a followup instead.

@@ -13,18 +13,16 @@ namespace RunTests
internal string DotnetFilePath { get; }
internal ProcDumpInfo? ProcDumpInfo { get; }
internal string TestResultsDirectory { get; }
internal string? Trait { get; }
internal string? NoTrait { get; }
internal string? TestFilter { get; }
Copy link
Member Author

Choose a reason for hiding this comment

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

As best as I could tell, the trait and notrait properties did not work properly with dotnet test. They would pass an argument like Trait=LanguageServerProtocol, but per https://docs.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests?pivots=xunit that isn't the correct format. So I modified these to be able to just pass in the xunit test filter (which also allowed me to pass in fully qualified names)

Copy link
Member

Choose a reason for hiding this comment

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

is it possible to extract this out into anotehr pR?

public void GoToDefinition(string viewName)
{
_editorInProc.GoToDefinition();
_editorInProc.WaitForActiveView(viewName);
Copy link
Member Author

Choose a reason for hiding this comment

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

LSP goto definition is async so we need to wait until the tab is opened. this shouldn't affect local tests as that tab will be opened immediately.

Copy link
Member

Choose a reason for hiding this comment

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

100ms doesn't seem long enough here. i coudl easily see things failing on CI because the machine is doing just a little bit of work, and can't open the window in time.

@dibarbet dibarbet marked this pull request as ready for review January 15, 2021 23:45
@dibarbet dibarbet requested review from a team as code owners January 15, 2021 23:45
@dibarbet dibarbet requested a review from a team as a code owner February 24, 2021 02:57
Copy link
Member

@JoeRobich JoeRobich left a comment

Choose a reason for hiding this comment

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

Infrastructure changes look good.

@dibarbet
Copy link
Member Author

I think I've addressed the feedback, let me know if there is any more
@CyrusNajmabadi @jasonmalinowski

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

Leaving comments so far.

@@ -372,6 +373,13 @@ function TestUsingRunTests() {
$args += " --sequential"
$args += " --include '\.IntegrationTests'"
$args += " --include 'Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests'"

if ($lspEditor) {
$args += " --testfilter FullyQualifiedName~Roslyn.VisualStudio.IntegrationTests.LanguageServerProtocol|Editor=LanguageServerProtocol"
Copy link
Member

@jasonmalinowski jasonmalinowski Mar 2, 2021

Choose a reason for hiding this comment

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

I guess the trait is sufficient right, if you just put the trait on containing types? My strong worry about the magic namespace is that we might rename or move something and not realize that tests aren't running anymore. Having the single method with the trait makes it a bit easier to know everything either works or doesn't.

@@ -372,6 +373,13 @@ function TestUsingRunTests() {
$args += " --sequential"
$args += " --include '\.IntegrationTests'"
$args += " --include 'Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests'"

if ($lspEditor) {
$args += " --testfilter FullyQualifiedName~Roslyn.VisualStudio.IntegrationTests.LanguageServerProtocol|Editor=LanguageServerProtocol"
Copy link
Member

Choose a reason for hiding this comment

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

(see other comment though that the only test currently in it's own namespace I think is better just combined with the existing test which checks if it's in LSP mode or not...)

@@ -372,6 +373,13 @@ function TestUsingRunTests() {
$args += " --sequential"
$args += " --include '\.IntegrationTests'"
$args += " --include 'Microsoft.CodeAnalysis.Workspaces.MSBuild.UnitTests'"

if ($lspEditor) {
$args += " --testfilter FullyQualifiedName~Roslyn.VisualStudio.IntegrationTests.LanguageServerProtocol|Editor=LanguageServerProtocol"
Copy link
Member

Choose a reason for hiding this comment

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

And yes, we once had an integration test CI that was passing because whatever glob was looking for assemblies to run wasn't updated, and so it was running nothing. That was a "fun" discovery.

@dibarbet dibarbet dismissed CyrusNajmabadi’s stale review March 2, 2021 05:17

stale, re-requested

@dibarbet
Copy link
Member Author

dibarbet commented Mar 2, 2021

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@@ -69,26 +69,30 @@ public void GoToDefinitionOpensProvisionalTabIfDocumentNotAlreadyOpen()
SomeClass sc;
}");
VisualStudio.Editor.PlaceCaret("SomeClass");
VisualStudio.Editor.GoToDefinition();
VisualStudio.Editor.GoToDefinition("FileDef.cs");
VisualStudio.Editor.Verify.TextContains(@"class SomeClass$$", assertCaretPosition: true);
Assert.True(VisualStudio.Shell.IsActiveTabProvisional());
}

[WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)]
Copy link
Member

Choose a reason for hiding this comment

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

So I would have expected xUnit would see this method through the inherited class as well, and then in the inherited copy see this method with LSP trait, so it'd run this in the LSP case as well. If this works it works, but not entirely sure what might happen here.

@dibarbet dibarbet merged commit ae76121 into dotnet:master Mar 3, 2021
@ghost ghost added this to the Next milestone Mar 3, 2021
@dibarbet dibarbet deleted the local_lsp branch March 3, 2021 00:29
@allisonchou allisonchou modified the milestones: Next, 16.10.P2 Mar 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE LSP issues related to the roslyn language server protocol implementation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants