python: Replace pyright with basedpyright (#35362)

Follow-up to #35250. Let's experiment with having this by default on
nightly.

Release Notes:

- Added built-in support for the basedpyright language server for Python
code. basedpyright is now enabled by default, and pyright (previously
the primary Python language server) remains available but is disabled by
default. This supersedes the basedpyright extension, which can be
uninstalled. Advantages of basedpyright over pyright include support for
inlay hints, semantic highlighting, auto-import code actions, and
stricter type checking. To switch back to pyright, add the following
configuration to settings.json:

```json
{
  "languages": {
    "Python": {
      "language_servers": ["pyright", "pylsp", "!basedpyright"]
    }
  }
}
```

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Lukas Wirth <lukas@zed.dev>
This commit is contained in:
Cole Miller
2025-09-08 19:15:17 +00:00
committed by GitHub
co-authored by Piotr Osiewicz Lukas Wirth
parent 99102a84fa
commit fa0df6da1c
14 changed files with 233 additions and 67 deletions
+95
View File
@@ -0,0 +1,95 @@
use db::kvp::Dismissable;
use editor::Editor;
use gpui::{Context, EventEmitter, Subscription};
use ui::{
Banner, Button, Clickable, Color, FluentBuilder as _, IconButton, IconName,
InteractiveElement as _, IntoElement, Label, LabelCommon, LabelSize, ParentElement as _,
Render, Styled as _, Window, div, h_flex, v_flex,
};
use workspace::{ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace};
pub struct BasedPyrightBanner {
dismissed: bool,
have_basedpyright: bool,
_subscriptions: [Subscription; 1],
}
impl Dismissable for BasedPyrightBanner {
const KEY: &str = "basedpyright-banner";
}
impl BasedPyrightBanner {
pub fn new(workspace: &Workspace, cx: &mut Context<Self>) -> Self {
let subscription = cx.subscribe(workspace.project(), |this, _, event, _| {
if let project::Event::LanguageServerAdded(_, name, _) = event
&& name == "basedpyright"
{
this.have_basedpyright = true;
}
});
let dismissed = Self::dismissed();
Self {
dismissed,
have_basedpyright: false,
_subscriptions: [subscription],
}
}
}
impl EventEmitter<ToolbarItemEvent> for BasedPyrightBanner {}
impl Render for BasedPyrightBanner {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.id("basedpyright-banner")
.when(!self.dismissed && self.have_basedpyright, |el| {
el.child(
Banner::new()
.severity(ui::Severity::Info)
.child(
h_flex()
.gap_2()
.child(v_flex()
.child("Basedpyright is now the only default language server for Python")
.child(Label::new("We have disabled PyRight and pylsp by default. They can be re-enabled in your settings.").size(LabelSize::XSmall).color(Color::Muted))
)
.child(
Button::new("learn-more", "Learn More")
.icon(IconName::ArrowUpRight)
.on_click(|_, _, cx| {
cx.open_url("https://zed.dev/docs/languages/python")
}),
),
)
.action_slot(IconButton::new("dismiss", IconName::Close).on_click(
cx.listener(|this, _, _, cx| {
this.dismissed = true;
Self::set_dismissed(true, cx);
cx.notify();
}),
))
.into_any_element(),
)
})
}
}
impl ToolbarItemView for BasedPyrightBanner {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn workspace::ItemHandle>,
_window: &mut ui::Window,
cx: &mut Context<Self>,
) -> ToolbarItemLocation {
if let Some(item) = active_pane_item
&& let Some(editor) = item.act_as::<Editor>(cx)
&& let Some(path) = editor.update(cx, |editor, cx| editor.target_file_abs_path(cx))
&& let Some(file_name) = path.file_name()
&& file_name.as_encoded_bytes().ends_with(".py".as_bytes())
{
return ToolbarItemLocation::Secondary;
}
ToolbarItemLocation::Hidden
}
}