-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Conversation
/// <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; } |
There was a problem hiding this comment.
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()); |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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/ --> |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs
Outdated
Show resolved
Hide resolved
/// <remarks> | ||
/// Currently utilized by Razor to intercept Roslyn's workspace/semanticTokens/refresh requests. | ||
/// </remarks> | ||
public object? MiddleLayer => _middleLayer; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRefreshListener.cs
Outdated
Show resolved
Hide resolved
src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs
Outdated
Show resolved
Hide resolved
@@ -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); |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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
src/Tools/ExternalAccess/Razor/RazorCSharpInterceptionMiddleLayer.cs
Outdated
Show resolved
Hide resolved
src/Features/LanguageServer/Protocol/Workspaces/LspWorkspaceManager.cs
Outdated
Show resolved
Hide resolved
src/Features/LanguageServer/Protocol/Handler/SemanticTokens/SemanticTokensRefreshListener.cs
Show resolved
Hide resolved
|
||
namespace Microsoft.CodeAnalysis.LanguageServer | ||
{ | ||
internal interface IRefreshListener : IDisposable |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
workspace/semanticTokens/refresh
support, which should improve perf by making polling obsolete.cc @gundermanc