Skip to content

Commit

Permalink
Add support for workspace/workspaceFolders request (#7990)
Browse files Browse the repository at this point in the history
* Add support for workspace/workspaceFolders message. New requirement from pylance

* Wasn't handling the project add/remove scenario too
  • Loading branch information
rchiodo authored Aug 30, 2024
1 parent e19e852 commit 436d1da
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 3 deletions.
1 change: 1 addition & 0 deletions Python/Product/PythonTools/PythonTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@
<Compile Include="PythonTools\LanguageServerClient\WorkspaceFolderChanged\DidChangeWorkspaceFoldersParams.cs" />
<Compile Include="PythonTools\LanguageServerClient\WorkspaceFolderChanged\WorkspaceFolder.cs" />
<Compile Include="PythonTools\LanguageServerClient\WorkspaceFolderChanged\WorkspaceFoldersChangeEvent.cs" />
<Compile Include="PythonTools\LanguageServerClient\WorkspaceFolders\WorkspaceFoldersArgs.cs" />
<Compile Include="PythonTools\Logging\LogHubLogger.cs" />
<Compile Include="PythonTools\Navigation\Navigable\NavigableSymbol.cs" />
<Compile Include="PythonTools\Navigation\Navigable\NavigableSymbolSource.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ internal sealed class PythonLanguageClient : ILanguageClient, ILanguageClientCus
private bool _workspaceFoldersSupported = false;
private bool _isDebugging = LanguageServer.IsDebugging();
private bool _sentInitialWorkspaceFolders = false;
private List<WorkspaceFolder> _workspaceFolders = new List<WorkspaceFolder>();
private FileWatcher.Listener _fileListener;
private static TaskCompletionSource<int> _readyTcs = new System.Threading.Tasks.TaskCompletionSource<int>();
private bool _loaded = false;
Expand Down Expand Up @@ -200,6 +201,7 @@ public async Task OnLoadedAsync() {
customTarget.WorkspaceFolderChangeRegistered += OnWorkspaceFolderWatched;
customTarget.AnalysisComplete += OnAnalysisComplete;
customTarget.WorkspaceConfiguration += OnWorkspaceConfiguration;
customTarget.WorkspaceFolders += OnWorkspaceFolders;
await StartAsync.InvokeAsync(this, EventArgs.Empty);
}

Expand Down Expand Up @@ -232,6 +234,11 @@ private async Task OnWorkspaceConfiguration(object sender, WorkspaceConfiguratio
args.requestResult = result.ToArray();
}

private async Task OnWorkspaceFolders(object sender, WorkspaceFolders.WorkspaceFoldersArgs args) {
// Return our current list of workspace folders
args.requestResult = this._workspaceFolders;
}

public async Task OnServerInitializedAsync() {
IsInitialized = true;
// Set _workspaceFoldersSupported to true and send to either workspace open or solution open
Expand Down Expand Up @@ -592,6 +599,7 @@ private async Task OnWorkspaceOpening(object sende, EventArgs e) {
// Send just this workspace folder. Assumption here is that the language client will be destroyed/recreated on
// each workspace open
var folder = new WorkspaceFolder { uri = new System.Uri(WorkspaceService.CurrentWorkspace.Location), name = WorkspaceService.CurrentWorkspace.GetName() };
this._workspaceFolders.Add(folder);
await InvokeDidChangeWorkspaceFoldersAsync(new WorkspaceFolder[] { folder }, new WorkspaceFolder[0]);
}
}
Expand All @@ -607,6 +615,7 @@ private void OnSolutionClosing() {
await InvokeDidChangeWorkspaceFoldersAsync(new WorkspaceFolder[0], folders.ToArray());
}
});
this._workspaceFolders.Clear();
_workspaceFoldersSupported = false;
IsInitialized = false;
_sentInitialWorkspaceFolders = false;
Expand All @@ -620,6 +629,7 @@ private void OnSolutionOpened() {
// If workspace folders are supported, then send our workspace folders
var folders = from n in this.ProjectContextProvider.ProjectNodes
select new WorkspaceFolder { uri = new System.Uri(n.BaseURI.Directory), name = n.Name };
this._workspaceFolders = new List<WorkspaceFolder>(folders);
if (folders.Any()) {
await InvokeDidChangeWorkspaceFoldersAsync(folders.ToArray(), new WorkspaceFolder[0]);
}
Expand All @@ -630,9 +640,10 @@ private void OnSolutionOpened() {
private void OnProjectAdded(EnvDTE.Project project) {
if (_workspaceFoldersSupported) {
JoinableTaskContext.Factory.RunAsync(async () => {
var pythonProject = project as PythonProjectNode;
var pythonProject = project.GetPythonProject() as PythonProjectNode;
if (pythonProject != null) {
var folder = new WorkspaceFolder { uri = new System.Uri(pythonProject.BaseURI.Directory), name = project.Name };
this._workspaceFolders.Add(folder);
await InvokeDidChangeWorkspaceFoldersAsync(new WorkspaceFolder[] { folder }, new WorkspaceFolder[0]);
}
});
Expand All @@ -642,9 +653,13 @@ private void OnProjectAdded(EnvDTE.Project project) {
private void OnProjectRemoved(EnvDTE.Project project) {
if (_workspaceFoldersSupported) {
JoinableTaskContext.Factory.RunAsync(async () => {
var pythonProject = project as PythonProjectNode;
var pythonProject = project.GetPythonProject() as PythonProjectNode;
if (pythonProject != null) {
var folder = new WorkspaceFolder { uri = new System.Uri(pythonProject.BaseURI.Directory), name = project.Name };
var entry = this._workspaceFolders.Find((f) => f.uri.ToString() == folder.uri.ToString());
if (entry != null) {
this._workspaceFolders.Remove(entry);
}
await InvokeDidChangeWorkspaceFoldersAsync(new WorkspaceFolder[0], new WorkspaceFolder[] { folder });
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

using Microsoft.PythonTools.LanguageServerClient.WorkspaceConfiguration;
using Microsoft.PythonTools.LanguageServerClient.FileWatcher;
using Microsoft.PythonTools.LanguageServerClient.WorkspaceFolders;

namespace Microsoft.PythonTools.LanguageServerClient {
internal class PythonLanguageClientCustomTarget {
Expand Down Expand Up @@ -89,6 +90,11 @@ public PythonLanguageClientCustomTarget(IServiceProvider site, JoinableTaskConte
/// </summary>
internal event AsyncEventHandler<ConfigurationArgs> WorkspaceConfiguration;

/// <summary>
/// Event fired when pylance sends a workspace/workspaceFolders request
/// </summary>
internal event AsyncEventHandler<WorkspaceFoldersArgs> WorkspaceFolders;

[JsonRpcMethod("telemetry/event")]
public void OnTelemetryEvent(JToken arg) {
if (!(arg is JObject telemetry)) {
Expand Down Expand Up @@ -175,5 +181,23 @@ public async Task<object> OnWorkspaceConfiguration(JToken arg) {
return null;
}
}

[JsonRpcMethod("workspace/workspaceFolders")]
public async Task<object> OnWorkspaceFolders() {
try {
// Should be no arguments (see request here: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_workspaceFolders)
if (this.WorkspaceFolders != null) {
var eventArgs = new WorkspaceFoldersArgs { requestResult = null };
await this.WorkspaceFolders.InvokeAsync(this, eventArgs);
return eventArgs.requestResult;
}
return null;
} catch {
return null;
}
}
}

internal class EmptyEventArgs {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.PythonTools.LanguageServerClient.WorkspaceFolders {
internal class WorkspaceFoldersArgs {
public object requestResult;
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"name": "ptvs",
"private": true,
"devDependencies": {
"@pylance/pylance": "2024.8.1"
"@pylance/pylance": "2024.8.2"
}
}

0 comments on commit 436d1da

Please sign in to comment.