private async Task ReanalyzeWorkspaceHelperAsync(IPythonInterpreterFactory factory, Redirector log) { _site.MustBeCalledFromUIThread(); try { if (!_recreatingAnalyzer.Wait(0)) { // Someone else is recreating, so wait for them to finish and return log?.WriteLine("Waiting for existing call"); await _recreatingAnalyzer.WaitAsync(); try { log?.WriteLine("Existing call complete"); } catch { _recreatingAnalyzer.Release(); throw; } if (_analyzer?.InterpreterFactory == factory) { _recreatingAnalyzer.Release(); return; } } } catch (ObjectDisposedException) { return; } IVsStatusbar statusBar = null; bool statusBarConfigured = false; try { if ((statusBar = _site.GetService(typeof(SVsStatusbar)) as IVsStatusbar) != null) { statusBar.SetText(Strings.AnalyzingProject); try { object index = (short)0; statusBar.Animation(1, ref index); } catch (ArgumentNullException) { // Issue in status bar implementation // https://github.com/Microsoft/PTVS/issues/3064 // Silently suppress since animation is not critical. } statusBar.FreezeOutput(1); statusBarConfigured = true; } var oldWatcher = _workspaceFileWatcher; _workspaceFileWatcher = new FileWatcher(_pythonWorkspace.Location) { EnableRaisingEvents = true, IncludeSubdirectories = true, NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite }; _workspaceFileWatcher.Changed += OnWorkspaceFileChanged; _workspaceFileWatcher.Deleted += OnWorkspaceFileDeleted; oldWatcher?.Dispose(); log?.WriteLine("Creating new workspace analyzer"); var analyzer = await CreateAnalyzerAsync(factory, _pythonWorkspace.Location); Debug.Assert(analyzer != null); log?.WriteLine($"Created workspace analyzer {analyzer}"); WorkspaceAnalyzerChanging?.Invoke(this, new AnalyzerChangingEventArgs(_analyzer, analyzer)); var oldAnalyzer = Interlocked.Exchange(ref _analyzer, analyzer); if (oldAnalyzer != null) { if (analyzer != null) { int beforeCount = analyzer.Files.Count(); log?.WriteLine($"Transferring from old analyzer {oldAnalyzer}, which has {oldAnalyzer.Files.Count()} files"); await analyzer.TransferFromOldAnalyzer(oldAnalyzer); log?.WriteLine($"Tranferred {analyzer.Files.Count() - beforeCount} files"); log?.WriteLine($"Old analyzer now has {oldAnalyzer.Files.Count()} files"); } if (oldAnalyzer.RemoveUser()) { log?.WriteLine("Disposing old analyzer"); oldAnalyzer.Dispose(); } } var files = new List <string>(); var pythonServices = _site.GetPythonToolsService(); foreach (var existing in pythonServices.GetActiveSharedAnalyzers().Select(kv => kv.Value).Where(v => !v.IsDisposed)) { foreach (var kv in existing.LoadedFiles) { files.Add(kv.Key); log?.WriteLine($"Unloading {kv.Key} from default analyzer"); foreach (var b in (kv.Value.TryGetBufferParser()?.AllBuffers).MaybeEnumerate()) { PythonTextBufferInfo.MarkForReplacement(b); } try { await existing.UnloadFileAsync(kv.Value); } catch (ObjectDisposedException) { break; } } } if (analyzer != null) { // Set search paths first, as it will save full reanalysis later log?.WriteLine("Setting search paths"); await analyzer.SetSearchPathsAsync(_pythonWorkspace.GetAbsoluteSearchPaths()); // Add all our files into our analyzer log?.WriteLine($"Adding {files.Count} files"); await analyzer.AnalyzeFileAsync(files.ToArray()); } WorkspaceAnalyzerChanged?.Invoke(this, EventArgs.Empty); } catch (ObjectDisposedException) { // Raced with disposal } catch (Exception ex) { log?.WriteErrorLine(ex.ToString()); throw; } finally { try { if (statusBar != null && statusBarConfigured) { statusBar.FreezeOutput(0); object index = (short)0; statusBar.Animation(0, ref index); statusBar.Clear(); } } finally { try { _recreatingAnalyzer.Release(); } catch (ObjectDisposedException) { } } } }