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

[LSP] Implement support for workspace/semanticTokens/refresh notifications #60824

Merged
merged 16 commits into from
Apr 22, 2022

Conversation

allisonchou
Copy link
Contributor

@allisonchou allisonchou commented Apr 18, 2022

  • This needs to wait for the LSP side PR to be merged + inserted first.
  • Implements workspace/semanticTokens/refresh support, which should improve perf by making polling obsolete.
  • There is an existing bug in the LSP client with middle layer interceptors that makes testing with Razor not possible. Will wait on merging this PR until that bug is fixed + I've manually tested the scenarios.
  • There is also a Razor side PR since they need to intercept Roslyn's messages: Intercept C# semantic tokens refresh messages razor#6298

cc @gundermanc

@allisonchou allisonchou added the LSP issues related to the roslyn language server protocol implementation label Apr 18, 2022
@allisonchou allisonchou requested review from a team as code owners April 18, 2022 22:40
/// <summary>
/// Gets a value indicating whether a notification bubble show be shown when the language server fails to initialize.
/// </summary>
public abstract bool ShowNotificationOnInitializeFailed { get; }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just moved this property up to fit in with the rest of the properties

// differentiate between the different C# LSP servers that have the same client name.
// We also don't use the language client's name property as it is a localized user facing string
// which is difficult to write telemetry queries for.
_requestTelemetryLogger = new RequestTelemetryLogger(_serverKind.ToTelemetryString());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved these two values up to LanguageServerTarget since they're needed by the semantic tokens refresh listener

_workQueue = new AsyncBatchingWorkQueue(
delay: TimeSpan.FromMilliseconds(2000),
processBatchAsync: SendSemanticTokensRefreshNotificationAsync,
asyncListener: listener,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wasn't sure what the correct value of asyncListener should be here - currently it's FeatureAttribute.LanguageServer, but not sure if we want that or FeatureAttribute.Workspace instead

@@ -131,6 +142,10 @@ public Task<InitializeResult> InitializeAsync(InitializeParams initializeParams,

Contract.ThrowIfTrue(_clientCapabilities != null, $"{nameof(InitializeAsync)} called multiple times");
_clientCapabilities = initializeParams.Capabilities;

// TO-DO: Add client capability check below once LSP side is merged
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before merging this PR, will add a client capability check for refresh once LSP side is merged - https://devdiv.visualstudio.com/DevDiv/_git/VSLanguageServerClient/pullrequest/388715

@@ -46,6 +46,16 @@
<ProjectReference Include="..\..\..\Workspaces\Remote\Core\Microsoft.CodeAnalysis.Remote.Workspaces.csproj" />
</ItemGroup>

<ItemGroup>
<!-- No warn on NU1701 until the LSP client targets netstandard2.0 https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1369985/ -->
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was adapted from EditorFeatures.csproj in order to include the VS LSP client package reference, which is needed for access to the ILanguageClientMiddleLayer type.

@dibarbet it looks like the underlying issue here was marked as "completed" but I'm still seeing the same errors mentioned in the internal issue. Would you have any context here?

Copy link
Member

Choose a reason for hiding this comment

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

@allisonchou depending on when the bug was completed, we may need to depend on an updated version of the VS language client
https://github.com/dotnet/roslyn/blob/main/eng/Versions.props#L155

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It looks like the bug was completed in mid-January, however I attempted updating to a client version from February and the problem persists. I'll comment on the original bug to ask

/// <remarks>
/// Currently utilized by Razor to intercept Roslyn's workspace/semanticTokens/refresh requests.
/// </remarks>
public object? MiddleLayer => _middleLayer;
Copy link
Member

Choose a reason for hiding this comment

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

Interesting - why do we need to support a middle layer here? Shouldn't that be possible entirely on the client side?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can specify the middle layer as part of the ILanguageClientCustomMessage2 interface, which the client then uses to send messages through the interceptors. I'm thinking it's meant to be specified on the server side so we can specify the middle layer we want, otherwise the client could send requests to all the potential middle layers.

Copy link
Member

Choose a reason for hiding this comment

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

Interesting. It seems like it could be done via content type or lsp server name. But I dont generally have a problem with this, was just wondering

@@ -163,6 +165,9 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs e)
_workspaceToLspSolution[workspace] = null;
}

// Send a workspace changed notification to anyone subscribed. For example, this is important for semantic tokens refresh.
LspWorkspaceChanged?.Invoke(sender, e);
Copy link
Member

Choose a reason for hiding this comment

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

We may want to document that the event handler implementation for this should not do basically any synchronous work, as that will block here.

Right now the only implementation basically does nothing (good), but I'm wondering if there is a way to ensure this cannot block even if the implementation of the event does something bad. Async callback function is an obvious option, but doesn't allow for easy registration of listeners (@CyrusNajmabadi for ideas)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a huge bolded XML warning above the event handler. Would be curious if Cyrus has any ideas on how to improve this too though


namespace Microsoft.CodeAnalysis.LanguageServer
{
internal interface IRefreshListener : IDisposable
Copy link
Member

@dibarbet dibarbet Apr 19, 2022

Choose a reason for hiding this comment

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

I think this was probably my mistake for not being clear - what I meant was a wrapper interface around the jsonrpc object that has a SendNotification method that takes in the params and method name.

Then you import that wrapper interface into the semantic tokens notification thing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done! Hopefully the abstraction makes things easier in the future. I wasn't sure about naming, if you have any suggestions feel free to lmk

@allisonchou allisonchou merged commit 084365c into dotnet:main Apr 22, 2022
@ghost ghost added this to the Next milestone Apr 22, 2022
@allisonchou allisonchou deleted the SemanticTokensRefresh branch April 22, 2022 19:21
@dibarbet dibarbet modified the milestones: Next, 17.3.P1 Apr 25, 2022
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.

6 participants