-
Notifications
You must be signed in to change notification settings - Fork 675
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
Pylance will request PTVS to listen for "**/*" under root but we dont… #8059
Closed
bschnurr
wants to merge
2
commits into
microsoft:main
from
bschnurr:fix-pylance-reanalysis-on-env-change
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,7 +88,7 @@ internal sealed class PythonLanguageClient : ILanguageClient, ILanguageClientCus | |
private List<IPythonLanguageClientContext> _clientContexts = new List<IPythonLanguageClientContext>(); | ||
private PythonAnalysisOptions _analysisOptions; | ||
private PythonAdvancedEditorOptions _advancedEditorOptions; | ||
private ITaskList _taskListService; | ||
private ITaskList _taskListService; | ||
private LanguageServer _server; | ||
private JsonRpc _rpc; | ||
private bool _workspaceFoldersSupported = false; | ||
|
@@ -99,7 +99,7 @@ internal sealed class PythonLanguageClient : ILanguageClient, ILanguageClientCus | |
private static TaskCompletionSource<int> _readyTcs = new TaskCompletionSource<int>(); | ||
private bool _loaded = false; | ||
private Timer _deferredSettingsChangedTimer; | ||
private const int _defaultSettingsDelayMS = 2000; | ||
private const int _defaultSettingsDelayMS = 5000; | ||
|
||
public PythonLanguageClient() { | ||
_disposables = new Common.Core.Disposables.DisposableBag(GetType().Name); | ||
|
@@ -152,10 +152,10 @@ public async Task<Connection> ActivateAsync(CancellationToken token) { | |
|
||
_disposables.Add(() => { | ||
_clientContexts.ForEach(c => { | ||
c.InterpreterChanged -= OnSettingsChanged; | ||
c.InterpreterChanged -= OnInterpreterChanged; | ||
c.SearchPathsChanged -= OnSettingsChanged; | ||
c.ReanalyzeChanged -= OnReanalyzeChanged; | ||
}); | ||
}); | ||
_analysisOptions.Changed -= OnSettingsChanged; | ||
_advancedEditorOptions.Changed -= OnSettingsChanged; | ||
|
||
|
@@ -164,7 +164,7 @@ public async Task<Connection> ActivateAsync(CancellationToken token) { | |
taskListService.PropertyChanged -= OnSettingsChanged; | ||
} catch (ServiceUnavailableException) { | ||
} | ||
|
||
_clientContexts.ForEach(c => c.Dispose()); | ||
_clientContexts.Clear(); | ||
solutionEvents.Opened -= OnSolutionOpened; | ||
|
@@ -215,7 +215,7 @@ private async Task OnWorkspaceConfiguration(object sender, WorkspaceConfiguratio | |
|
||
var pythonSetting = GetSettings(item.scopeUri); | ||
|
||
if(pythonSetting == null) { | ||
if (pythonSetting == null) { | ||
continue; | ||
} | ||
|
||
|
@@ -256,7 +256,7 @@ public Task OnServerInitializeFailedAsync(Exception e) { | |
} | ||
|
||
public Task AttachForCustomMessageAsync(JsonRpc rpc) { | ||
|
||
_rpc = rpc; | ||
|
||
// This is a workaround until we have proper API from ILanguageClient for now. | ||
|
@@ -269,7 +269,6 @@ public Task AttachForCustomMessageAsync(JsonRpc rpc) { | |
_fileListener = null; | ||
_fileListener = new FileWatcher.Listener(_rpc, WorkspaceService, Site); | ||
_disposables.Add(_fileListener); | ||
|
||
// We also need to switch the order on handlers for all of the rpc targets. Until | ||
// the VSSDK gives us a way to do this, use reflection. | ||
try { | ||
|
@@ -301,15 +300,15 @@ public Task AttachForCustomMessageAsync(JsonRpc rpc) { | |
} catch { | ||
// Any exceptions, just skip this part | ||
} | ||
|
||
return Task.CompletedTask; | ||
} | ||
|
||
public void Dispose() => _disposables.TryDispose(); | ||
|
||
public void AddClientContext(IPythonLanguageClientContext context) { | ||
_clientContexts.Add(context); | ||
context.InterpreterChanged += OnSettingsChanged; | ||
context.InterpreterChanged += OnInterpreterChanged; | ||
context.SearchPathsChanged += OnSettingsChanged; | ||
context.ReanalyzeChanged += OnReanalyzeChanged; | ||
} | ||
|
@@ -367,16 +366,15 @@ private async Task NotifyWithParametersAsync(string request, object parameters) | |
await _rpc.NotifyWithParameterObjectAsync(request, parameters).ConfigureAwait(false); | ||
} | ||
|
||
private LanguageServerSettings.PythonSettings GetSettings(Uri scopeUri = null) | ||
{ | ||
private LanguageServerSettings.PythonSettings GetSettings(Uri scopeUri = null) { | ||
IPythonLanguageClientContext context = null; | ||
if (scopeUri == null) { | ||
// REPL context has null RootPath | ||
context = _clientContexts.Find(c => c.RootPath == null); | ||
if (context == null) { | ||
if (context == null) { | ||
return null; | ||
} | ||
}else { | ||
} else { | ||
var pathFromScopeUri = CommonUtils.NormalizeDirectoryPath(scopeUri.LocalPath).ToLower().TrimStart('\\'); | ||
// Find the matching context for the item, but ignore interactive window where "RootPath" is null. | ||
context = _clientContexts.Find(c => scopeUri != null && c.RootPath != null && PathUtils.IsSamePath(c.RootPath.ToLower(), pathFromScopeUri)); | ||
|
@@ -408,12 +406,9 @@ private LanguageServerSettings.PythonSettings GetSettings(Uri scopeUri = null) | |
// get task list tokens from options | ||
var taskListTokens = new List<LanguageServerSettings.PythonSettings.PythonAnalysisSettings.TaskListToken>(); | ||
var taskListService = Site.GetService<SVsTaskList, ITaskList>(); | ||
if (taskListService != null) | ||
{ | ||
foreach (var commentToken in taskListService.CommentTokens) | ||
{ | ||
taskListTokens.Add(new LanguageServerSettings.PythonSettings.PythonAnalysisSettings.TaskListToken() | ||
{ | ||
if (taskListService != null) { | ||
foreach (var commentToken in taskListService.CommentTokens) { | ||
taskListTokens.Add(new LanguageServerSettings.PythonSettings.PythonAnalysisSettings.TaskListToken() { | ||
text = commentToken.Text, | ||
priority = commentToken.Priority.ToString() | ||
}); | ||
|
@@ -449,6 +444,21 @@ private LanguageServerSettings.PythonSettings GetSettings(Uri scopeUri = null) | |
return settings; | ||
|
||
} | ||
private void OnInterpreterChanged(object sender, EventArgs e) { | ||
|
||
// By default Pylance will tell us to watch everything under the workspace with pattern "**/*" | ||
// we can exclude the interpreter directory because we already have package managers listening to them | ||
this._clientContexts.ForEach(context => { | ||
|
||
if (PathUtils.IsSubpathOf(context.RootPath, context.InterpreterConfiguration.InterpreterPath)) { | ||
var pattern = CommonUtils.GetRelativeFilePath(context.RootPath, context.InterpreterConfiguration.GetPrefixPath()) + "/**/*"; | ||
var watcher = new FileSystemWatcher() { GlobPattern = pattern }; | ||
this._fileListener.AddExclude(watcher); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the fix. just exclude files under the interpreter if the interpreter is under the root workspace |
||
} | ||
|
||
}); | ||
OnSettingsChanged(sender, e); | ||
} | ||
|
||
private void OnSettingsChanged(object sender, EventArgs e) { | ||
try { | ||
|
@@ -470,7 +480,7 @@ private void OnReanalyzeChanged(object sender, EventArgs e) { | |
} catch (ObjectDisposedException) { | ||
} | ||
} | ||
|
||
private bool TryGetOpenedDocumentData(RunningDocumentInfo info, out ITextBuffer textBuffer, out string filePath) { | ||
textBuffer = null; | ||
filePath = string.Empty; | ||
|
@@ -514,8 +524,16 @@ private void OnWorkspaceFolderWatched(object sender, EventArgs e) { | |
} | ||
|
||
private void WatchedFilesRegistered(object sender, DidChangeWatchedFilesRegistrationOptions e) { | ||
// Add the file globs to our listener. It will listen to the globs | ||
_fileListener?.AddPatterns(e.Watchers); | ||
|
||
//this._clientContexts.ForEach(context => { | ||
|
||
// if (PathUtils.IsSubpathOf(context.RootPath, context.InterpreterConfiguration.InterpreterPath)) { | ||
// var pattern = CommonUtils.GetRelativeFilePath(context.RootPath, context.InterpreterConfiguration.GetPrefixPath()) + "/**/*"; | ||
// var watcher = new FileSystemWatcher() { GlobPattern = pattern }; | ||
// this._fileListener.AddExclude(watcher); | ||
// } | ||
|
||
//}); | ||
} | ||
|
||
private void CreateClientContexts() { | ||
|
@@ -549,7 +567,7 @@ private Tuple<StreamData, bool> OnSendToServer(StreamData data) { | |
capabilities["workspace"]["workspaceFolders"] = true; | ||
capabilities["workspace"]["didChangeWatchedFiles"]["dynamicRegistration"] = true; | ||
capabilities["workspace"]["configuration"] = true; | ||
|
||
var folders = GetFolders(); | ||
Debug.Assert(folders.Any(), "no workspace or projects found"); | ||
messageParams["workspaceFolders"] = JToken.FromObject(folders.ToArray()); | ||
|
@@ -569,15 +587,15 @@ private Tuple<StreamData, bool> OnSendToServer(StreamData data) { | |
} | ||
} else if (message.Value<string>("method") == "textDocument/codeAction") { | ||
if (message.TryGetValue("params", out JToken messageParams)) { | ||
if (messageParams != null && messageParams["range"] != null | ||
&& messageParams["context"] != null | ||
if (messageParams != null && messageParams["range"] != null | ||
&& messageParams["context"] != null | ||
&& messageParams["context"]["_vs_selectionRange"] != null) { | ||
var selectionRange = messageParams["context"]["_vs_selectionRange"]; | ||
messageParams["range"]["start"] = selectionRange["start"]; | ||
messageParams["range"]["end"] = selectionRange["end"]; | ||
return Tuple.Create(MessageParser.Serialize(message), true); | ||
} | ||
|
||
} | ||
} | ||
} catch { | ||
|
@@ -596,7 +614,7 @@ private List<WorkspaceFolder> GetFolders() { | |
return [folder]; | ||
} else { | ||
var folders = from n in this.ProjectContextProvider.ProjectNodes | ||
select new WorkspaceFolder { uri = new System.Uri(n.BaseURI.Directory), name = n.Name }; | ||
select new WorkspaceFolder { uri = new System.Uri(n.BaseURI.Directory), name = n.Name }; | ||
return folders.ToList(); | ||
} | ||
} | ||
|
@@ -607,11 +625,11 @@ private async Task OnWorkspaceOpening(object sender, EventArgs e) { | |
// Send just this workspace folder. Assumption here is that the language client will be destroyed/recreated on | ||
// each workspace open | ||
var folders = GetFolders(); | ||
this._workspaceFolders= folders.ToList(); | ||
this._workspaceFolders = folders.ToList(); | ||
await InvokeDidChangeWorkspaceFoldersAsync(folders.ToArray(), new WorkspaceFolder[0]); | ||
} | ||
} | ||
|
||
// Note this is called for both openFolder and openProject modes | ||
private void OnSolutionClosing() { | ||
this._clientContexts.Clear(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
increasing settings delay helps delay analysis on while installing new packages