python: Fix toolchains not getting picked up after workspace deserialization (#20488)

Piotr Osiewicz created

Closes #20476

Release Notes:

- Fixed a bug in toolchain selector that caused it to not pick up venvs
for tabs before user interacted with them.
- Fixed a bug in language selector that caused it to pick up Markdown as
the language for a buffer up until the tab was interacted with.

Change summary

crates/language_selector/src/active_buffer_language.rs |  2 
crates/toolchain_selector/src/active_toolchain.rs      | 25 +++--------
2 files changed, 9 insertions(+), 18 deletions(-)

Detailed changes

crates/language_selector/src/active_buffer_language.rs 🔗

@@ -66,7 +66,7 @@ impl StatusItemView for ActiveBufferLanguage {
         active_pane_item: Option<&dyn ItemHandle>,
         cx: &mut ViewContext<Self>,
     ) {
-        if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
+        if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
             self._observe_active_editor = Some(cx.observe(&editor, Self::update_language));
             self.update_language(editor, cx);
         } else {

crates/toolchain_selector/src/active_toolchain.rs 🔗

@@ -1,7 +1,7 @@
 use editor::Editor;
 use gpui::{
-    div, AsyncWindowContext, EventEmitter, IntoElement, ParentElement, Render, Subscription, Task,
-    View, ViewContext, WeakModel, WeakView,
+    div, AsyncWindowContext, IntoElement, ParentElement, Render, Subscription, Task, View,
+    ViewContext, WeakModel, WeakView,
 };
 use language::{Buffer, BufferEvent, LanguageName, Toolchain};
 use project::WorktreeId;
@@ -14,24 +14,16 @@ pub struct ActiveToolchain {
     active_toolchain: Option<Toolchain>,
     workspace: WeakView<Workspace>,
     active_buffer: Option<(WorktreeId, WeakModel<Buffer>, Subscription)>,
-    _observe_language_changes: Subscription,
     _update_toolchain_task: Task<Option<()>>,
 }
 
-struct LanguageChanged;
-
-impl EventEmitter<LanguageChanged> for ActiveToolchain {}
-
 impl ActiveToolchain {
     pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
-        let view = cx.view().clone();
         Self {
             active_toolchain: None,
             active_buffer: None,
             workspace: workspace.weak_handle(),
-            _observe_language_changes: cx.subscribe(&view, |this, _, _: &LanguageChanged, cx| {
-                this._update_toolchain_task = Self::spawn_tracker_task(cx);
-            }),
+
             _update_toolchain_task: Self::spawn_tracker_task(cx),
         }
     }
@@ -48,7 +40,6 @@ impl ActiveToolchain {
             let workspace = this
                 .update(&mut cx, |this, _| this.workspace.clone())
                 .ok()?;
-
             let language_name = active_file
                 .update(&mut cx, |this, _| Some(this.language()?.name()))
                 .ok()
@@ -73,13 +64,13 @@ impl ActiveToolchain {
         let editor = editor.read(cx);
         if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
             if let Some(worktree_id) = buffer.read(cx).file().map(|file| file.worktree_id(cx)) {
-                let subscription = cx.subscribe(&buffer, |_, _, event: &BufferEvent, cx| {
-                    if let BufferEvent::LanguageChanged = event {
-                        cx.emit(LanguageChanged)
+                let subscription = cx.subscribe(&buffer, |this, _, event: &BufferEvent, cx| {
+                    if matches!(event, BufferEvent::LanguageChanged) {
+                        this._update_toolchain_task = Self::spawn_tracker_task(cx);
                     }
                 });
                 self.active_buffer = Some((worktree_id, buffer.downgrade(), subscription));
-                cx.emit(LanguageChanged);
+                self._update_toolchain_task = Self::spawn_tracker_task(cx);
             }
         }
 
@@ -164,7 +155,7 @@ impl StatusItemView for ActiveToolchain {
         active_pane_item: Option<&dyn ItemHandle>,
         cx: &mut ViewContext<Self>,
     ) {
-        if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
+        if let Some(editor) = active_pane_item.and_then(|item| item.downcast::<Editor>()) {
             self.active_toolchain.take();
             self.update_lister(editor, cx);
         }