Detailed changes
@@ -4278,7 +4278,6 @@ dependencies = [
"db",
"debugger_tools",
"editor",
- "feature_flags",
"file_icons",
"futures 0.3.31",
"fuzzy",
@@ -4746,7 +4745,6 @@ dependencies = [
"dap",
"db",
"emojis",
- "feature_flags",
"file_icons",
"fs",
"futures 0.3.31",
@@ -19994,7 +19992,6 @@ dependencies = [
"extension",
"extension_host",
"extensions_ui",
- "feature_flags",
"feedback",
"file_finder",
"fs",
@@ -35,7 +35,6 @@ dap.workspace = true
dap_adapters = { workspace = true, optional = true }
db.workspace = true
editor.workspace = true
-feature_flags.workspace = true
file_icons.workspace = true
futures.workspace = true
fuzzy.workspace = true
@@ -3,7 +3,6 @@ use std::any::TypeId;
use dap::debugger_settings::DebuggerSettings;
use debugger_panel::{DebugPanel, ToggleFocus};
use editor::Editor;
-use feature_flags::{DebuggerFeatureFlag, FeatureFlagViewExt};
use gpui::{App, DispatchPhase, EntityInputHandler, actions};
use new_process_modal::{NewProcessModal, NewProcessMode};
use project::debugger::{self, breakpoint_store::SourceBreakpoint, session::ThreadStatus};
@@ -62,173 +61,163 @@ pub fn init(cx: &mut App) {
DebuggerSettings::register(cx);
workspace::FollowableViewRegistry::register::<DebugSession>(cx);
- cx.observe_new(|_: &mut Workspace, window, cx| {
- let Some(window) = window else {
- return;
- };
-
- cx.when_flag_enabled::<DebuggerFeatureFlag>(window, |workspace, _, _| {
- workspace
- .register_action(spawn_task_or_modal)
- .register_action(|workspace, _: &ToggleFocus, window, cx| {
- workspace.toggle_panel_focus::<DebugPanel>(window, cx);
- })
- .register_action(|workspace: &mut Workspace, _: &Start, window, cx| {
- NewProcessModal::show(workspace, window, NewProcessMode::Debug, None, cx);
- })
- .register_action(
- |workspace: &mut Workspace, _: &RerunLastSession, window, cx| {
- let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
- return;
- };
-
- debug_panel.update(cx, |debug_panel, cx| {
- debug_panel.rerun_last_session(workspace, window, cx);
- })
- },
- )
- .register_action(
- |workspace: &mut Workspace, _: &ShutdownDebugAdapters, _window, cx| {
- workspace.project().update(cx, |project, cx| {
- project.dap_store().update(cx, |store, cx| {
- store.shutdown_sessions(cx).detach();
- })
- })
- },
- )
- .register_action_renderer(|div, workspace, _, cx| {
+ cx.observe_new(|workspace: &mut Workspace, _, _| {
+ workspace
+ .register_action(spawn_task_or_modal)
+ .register_action(|workspace, _: &ToggleFocus, window, cx| {
+ workspace.toggle_panel_focus::<DebugPanel>(window, cx);
+ })
+ .register_action(|workspace: &mut Workspace, _: &Start, window, cx| {
+ NewProcessModal::show(workspace, window, NewProcessMode::Debug, None, cx);
+ })
+ .register_action(
+ |workspace: &mut Workspace, _: &RerunLastSession, window, cx| {
let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
- return div;
- };
- let Some(active_item) = debug_panel
- .read(cx)
- .active_session()
- .map(|session| session.read(cx).running_state().clone())
- else {
- return div;
+ return;
};
- let running_state = active_item.read(cx);
- if running_state.session().read(cx).is_terminated() {
- return div;
- }
- let caps = running_state.capabilities(cx);
- let supports_step_back = caps.supports_step_back.unwrap_or_default();
- let supports_detach = running_state.session().read(cx).is_attached();
- let status = running_state.thread_status(cx);
-
- let active_item = active_item.downgrade();
- div.when(status == Some(ThreadStatus::Running), |div| {
- let active_item = active_item.clone();
- div.on_action(move |_: &Pause, _, cx| {
- active_item
- .update(cx, |item, cx| item.pause_thread(cx))
- .ok();
- })
+ debug_panel.update(cx, |debug_panel, cx| {
+ debug_panel.rerun_last_session(workspace, window, cx);
})
- .when(status == Some(ThreadStatus::Stopped), |div| {
- div.on_action({
- let active_item = active_item.clone();
- move |_: &StepInto, _, cx| {
- active_item.update(cx, |item, cx| item.step_in(cx)).ok();
- }
- })
- .on_action({
- let active_item = active_item.clone();
- move |_: &StepOver, _, cx| {
- active_item.update(cx, |item, cx| item.step_over(cx)).ok();
- }
- })
- .on_action({
- let active_item = active_item.clone();
- move |_: &StepOut, _, cx| {
- active_item.update(cx, |item, cx| item.step_out(cx)).ok();
- }
- })
- .when(supports_step_back, |div| {
- let active_item = active_item.clone();
- div.on_action(move |_: &StepBack, _, cx| {
- active_item.update(cx, |item, cx| item.step_back(cx)).ok();
- })
- })
- .on_action({
- let active_item = active_item.clone();
- move |_: &Continue, _, cx| {
- active_item
- .update(cx, |item, cx| item.continue_thread(cx))
- .ok();
- }
+ },
+ )
+ .register_action(
+ |workspace: &mut Workspace, _: &ShutdownDebugAdapters, _window, cx| {
+ workspace.project().update(cx, |project, cx| {
+ project.dap_store().update(cx, |store, cx| {
+ store.shutdown_sessions(cx).detach();
})
- .on_action(cx.listener(
- |workspace, _: &ShowStackTrace, window, cx| {
- let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
- return;
- };
-
- if let Some(existing) = workspace.item_of_type::<StackTraceView>(cx)
- {
- let is_active = workspace
- .active_item(cx)
- .is_some_and(|item| item.item_id() == existing.item_id());
- workspace
- .activate_item(&existing, true, !is_active, window, cx);
- } else {
- let Some(active_session) =
- debug_panel.read(cx).active_session()
- else {
- return;
- };
-
- let project = workspace.project();
+ })
+ },
+ )
+ .register_action_renderer(|div, workspace, _, cx| {
+ let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
+ return div;
+ };
+ let Some(active_item) = debug_panel
+ .read(cx)
+ .active_session()
+ .map(|session| session.read(cx).running_state().clone())
+ else {
+ return div;
+ };
+ let running_state = active_item.read(cx);
+ if running_state.session().read(cx).is_terminated() {
+ return div;
+ }
- let stack_trace_view =
- active_session.update(cx, |session, cx| {
- session.stack_trace_view(project, window, cx).clone()
- });
+ let caps = running_state.capabilities(cx);
+ let supports_step_back = caps.supports_step_back.unwrap_or_default();
+ let supports_detach = running_state.session().read(cx).is_attached();
+ let status = running_state.thread_status(cx);
- workspace.add_item_to_active_pane(
- Box::new(stack_trace_view),
- None,
- true,
- window,
- cx,
- );
- }
- },
- ))
+ let active_item = active_item.downgrade();
+ div.when(status == Some(ThreadStatus::Running), |div| {
+ let active_item = active_item.clone();
+ div.on_action(move |_: &Pause, _, cx| {
+ active_item
+ .update(cx, |item, cx| item.pause_thread(cx))
+ .ok();
})
- .when(supports_detach, |div| {
+ })
+ .when(status == Some(ThreadStatus::Stopped), |div| {
+ div.on_action({
let active_item = active_item.clone();
- div.on_action(move |_: &Detach, _, cx| {
- active_item
- .update(cx, |item, cx| item.detach_client(cx))
- .ok();
- })
+ move |_: &StepInto, _, cx| {
+ active_item.update(cx, |item, cx| item.step_in(cx)).ok();
+ }
})
.on_action({
let active_item = active_item.clone();
- move |_: &Restart, _, cx| {
- active_item
- .update(cx, |item, cx| item.restart_session(cx))
- .ok();
+ move |_: &StepOver, _, cx| {
+ active_item.update(cx, |item, cx| item.step_over(cx)).ok();
}
})
.on_action({
let active_item = active_item.clone();
- move |_: &Stop, _, cx| {
- active_item.update(cx, |item, cx| item.stop_thread(cx)).ok();
+ move |_: &StepOut, _, cx| {
+ active_item.update(cx, |item, cx| item.step_out(cx)).ok();
}
})
+ .when(supports_step_back, |div| {
+ let active_item = active_item.clone();
+ div.on_action(move |_: &StepBack, _, cx| {
+ active_item.update(cx, |item, cx| item.step_back(cx)).ok();
+ })
+ })
.on_action({
let active_item = active_item.clone();
- move |_: &ToggleIgnoreBreakpoints, _, cx| {
+ move |_: &Continue, _, cx| {
active_item
- .update(cx, |item, cx| item.toggle_ignore_breakpoints(cx))
+ .update(cx, |item, cx| item.continue_thread(cx))
.ok();
}
})
- });
- })
+ .on_action(cx.listener(
+ |workspace, _: &ShowStackTrace, window, cx| {
+ let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
+ return;
+ };
+
+ if let Some(existing) = workspace.item_of_type::<StackTraceView>(cx) {
+ let is_active = workspace
+ .active_item(cx)
+ .is_some_and(|item| item.item_id() == existing.item_id());
+ workspace.activate_item(&existing, true, !is_active, window, cx);
+ } else {
+ let Some(active_session) = debug_panel.read(cx).active_session()
+ else {
+ return;
+ };
+
+ let project = workspace.project();
+
+ let stack_trace_view = active_session.update(cx, |session, cx| {
+ session.stack_trace_view(project, window, cx).clone()
+ });
+
+ workspace.add_item_to_active_pane(
+ Box::new(stack_trace_view),
+ None,
+ true,
+ window,
+ cx,
+ );
+ }
+ },
+ ))
+ })
+ .when(supports_detach, |div| {
+ let active_item = active_item.clone();
+ div.on_action(move |_: &Detach, _, cx| {
+ active_item
+ .update(cx, |item, cx| item.detach_client(cx))
+ .ok();
+ })
+ })
+ .on_action({
+ let active_item = active_item.clone();
+ move |_: &Restart, _, cx| {
+ active_item
+ .update(cx, |item, cx| item.restart_session(cx))
+ .ok();
+ }
+ })
+ .on_action({
+ let active_item = active_item.clone();
+ move |_: &Stop, _, cx| {
+ active_item.update(cx, |item, cx| item.stop_thread(cx)).ok();
+ }
+ })
+ .on_action({
+ let active_item = active_item.clone();
+ move |_: &ToggleIgnoreBreakpoints, _, cx| {
+ active_item
+ .update(cx, |item, cx| item.toggle_ignore_breakpoints(cx))
+ .ok();
+ }
+ })
+ });
})
.detach();
@@ -40,7 +40,6 @@ dap.workspace = true
db.workspace = true
buffer_diff.workspace = true
emojis.workspace = true
-feature_flags.workspace = true
file_icons.workspace = true
futures.workspace = true
fuzzy.workspace = true
@@ -73,7 +73,6 @@ use element::{AcceptEditPredictionBinding, LineWithInvisibles, PositionMap, layo
pub use element::{
CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
};
-use feature_flags::{DebuggerFeatureFlag, FeatureFlagAppExt};
use futures::{
FutureExt, StreamExt as _,
future::{self, Shared, join},
@@ -5969,45 +5968,41 @@ impl Editor {
buffer: &Entity<Buffer>,
cx: &mut App,
) -> Task<Vec<task::DebugScenario>> {
- if cx.has_flag::<DebuggerFeatureFlag>() {
- maybe!({
- let project = self.project.as_ref()?;
- let dap_store = project.read(cx).dap_store();
- let mut scenarios = vec![];
- let resolved_tasks = resolved_tasks.as_ref()?;
- let buffer = buffer.read(cx);
- let language = buffer.language()?;
- let file = buffer.file();
- let debug_adapter = language_settings(language.name().into(), file, cx)
- .debuggers
- .first()
- .map(SharedString::from)
- .or_else(|| language.config().debuggers.first().map(SharedString::from))?;
-
- dap_store.update(cx, |dap_store, cx| {
- for (_, task) in &resolved_tasks.templates {
- let maybe_scenario = dap_store.debug_scenario_for_build_task(
- task.original_task().clone(),
- debug_adapter.clone().into(),
- task.display_label().to_owned().into(),
- cx,
- );
- scenarios.push(maybe_scenario);
- }
- });
- Some(cx.background_spawn(async move {
- let scenarios = futures::future::join_all(scenarios)
- .await
- .into_iter()
- .flatten()
- .collect::<Vec<_>>();
- scenarios
- }))
- })
- .unwrap_or_else(|| Task::ready(vec![]))
- } else {
- Task::ready(vec![])
- }
+ maybe!({
+ let project = self.project.as_ref()?;
+ let dap_store = project.read(cx).dap_store();
+ let mut scenarios = vec![];
+ let resolved_tasks = resolved_tasks.as_ref()?;
+ let buffer = buffer.read(cx);
+ let language = buffer.language()?;
+ let file = buffer.file();
+ let debug_adapter = language_settings(language.name().into(), file, cx)
+ .debuggers
+ .first()
+ .map(SharedString::from)
+ .or_else(|| language.config().debuggers.first().map(SharedString::from))?;
+
+ dap_store.update(cx, |dap_store, cx| {
+ for (_, task) in &resolved_tasks.templates {
+ let maybe_scenario = dap_store.debug_scenario_for_build_task(
+ task.original_task().clone(),
+ debug_adapter.clone().into(),
+ task.display_label().to_owned().into(),
+ cx,
+ );
+ scenarios.push(maybe_scenario);
+ }
+ });
+ Some(cx.background_spawn(async move {
+ let scenarios = futures::future::join_all(scenarios)
+ .await
+ .into_iter()
+ .flatten()
+ .collect::<Vec<_>>();
+ scenarios
+ }))
+ })
+ .unwrap_or_else(|| Task::ready(vec![]))
}
fn code_actions(
@@ -10155,9 +10150,6 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
- if !cx.has_flag::<DebuggerFeatureFlag>() {
- return;
- }
let source = self
.buffer
.read(cx)
@@ -32,7 +32,6 @@ use crate::{
};
use buffer_diff::{DiffHunkStatus, DiffHunkStatusKind};
use collections::{BTreeMap, HashMap};
-use feature_flags::{DebuggerFeatureFlag, FeatureFlagAppExt};
use file_icons::FileIcons;
use git::{
Oid,
@@ -567,12 +566,10 @@ impl EditorElement {
register_action(editor, window, Editor::insert_uuid_v4);
register_action(editor, window, Editor::insert_uuid_v7);
register_action(editor, window, Editor::open_selections_in_multibuffer);
- if cx.has_flag::<DebuggerFeatureFlag>() {
- register_action(editor, window, Editor::toggle_breakpoint);
- register_action(editor, window, Editor::edit_log_breakpoint);
- register_action(editor, window, Editor::enable_breakpoint);
- register_action(editor, window, Editor::disable_breakpoint);
- }
+ register_action(editor, window, Editor::toggle_breakpoint);
+ register_action(editor, window, Editor::edit_log_breakpoint);
+ register_action(editor, window, Editor::enable_breakpoint);
+ register_action(editor, window, Editor::disable_breakpoint);
}
fn register_key_listeners(&self, window: &mut Window, _: &mut App, layout: &EditorLayout) {
@@ -8173,11 +8170,9 @@ impl Element for EditorElement {
let mut breakpoint_rows = self.editor.update(cx, |editor, cx| {
editor.active_breakpoints(start_row..end_row, window, cx)
});
- if cx.has_flag::<DebuggerFeatureFlag>() {
- for (display_row, (_, bp, state)) in &breakpoint_rows {
- if bp.is_enabled() && state.is_none_or(|s| s.verified) {
- active_rows.entry(*display_row).or_default().breakpoint = true;
- }
+ for (display_row, (_, bp, state)) in &breakpoint_rows {
+ if bp.is_enabled() && state.is_none_or(|s| s.verified) {
+ active_rows.entry(*display_row).or_default().breakpoint = true;
}
}
@@ -8198,30 +8193,27 @@ impl Element for EditorElement {
// We add the gutter breakpoint indicator to breakpoint_rows after painting
// line numbers so we don't paint a line number debug accent color if a user
// has their mouse over that line when a breakpoint isn't there
- if cx.has_flag::<DebuggerFeatureFlag>() {
- self.editor.update(cx, |editor, _| {
- if let Some(phantom_breakpoint) = &mut editor
- .gutter_breakpoint_indicator
- .0
- .filter(|phantom_breakpoint| phantom_breakpoint.is_active)
- {
- // Is there a non-phantom breakpoint on this line?
- phantom_breakpoint.collides_with_existing_breakpoint = true;
- breakpoint_rows
- .entry(phantom_breakpoint.display_row)
- .or_insert_with(|| {
- let position = snapshot.display_point_to_anchor(
- DisplayPoint::new(phantom_breakpoint.display_row, 0),
- Bias::Right,
- );
- let breakpoint = Breakpoint::new_standard();
- phantom_breakpoint.collides_with_existing_breakpoint =
- false;
- (position, breakpoint, None)
- });
- }
- })
- }
+ self.editor.update(cx, |editor, _| {
+ if let Some(phantom_breakpoint) = &mut editor
+ .gutter_breakpoint_indicator
+ .0
+ .filter(|phantom_breakpoint| phantom_breakpoint.is_active)
+ {
+ // Is there a non-phantom breakpoint on this line?
+ phantom_breakpoint.collides_with_existing_breakpoint = true;
+ breakpoint_rows
+ .entry(phantom_breakpoint.display_row)
+ .or_insert_with(|| {
+ let position = snapshot.display_point_to_anchor(
+ DisplayPoint::new(phantom_breakpoint.display_row, 0),
+ Bias::Right,
+ );
+ let breakpoint = Breakpoint::new_standard();
+ phantom_breakpoint.collides_with_existing_breakpoint = false;
+ (position, breakpoint, None)
+ });
+ }
+ });
let mut expand_toggles =
window.with_element_namespace("expand_toggles", |window| {
@@ -8690,7 +8682,7 @@ impl Element for EditorElement {
let show_breakpoints = snapshot
.show_breakpoints
.unwrap_or(gutter_settings.breakpoints);
- let breakpoints = if cx.has_flag::<DebuggerFeatureFlag>() && show_breakpoints {
+ let breakpoints = if show_breakpoints {
self.layout_breakpoints(
line_height,
start_row..end_row,
@@ -8705,7 +8697,7 @@ impl Element for EditorElement {
cx,
)
} else {
- vec![]
+ Vec::new()
};
self.layout_signature_help(
@@ -77,11 +77,6 @@ impl FeatureFlag for NotebookFeatureFlag {
const NAME: &'static str = "notebooks";
}
-pub struct DebuggerFeatureFlag {}
-impl FeatureFlag for DebuggerFeatureFlag {
- const NAME: &'static str = "debugger";
-}
-
pub struct ThreadAutoCaptureFeatureFlag {}
impl FeatureFlag for ThreadAutoCaptureFeatureFlag {
const NAME: &'static str = "thread-auto-capture";
@@ -55,7 +55,6 @@ env_logger.workspace = true
extension.workspace = true
extension_host.workspace = true
extensions_ui.workspace = true
-feature_flags.workspace = true
feedback.workspace = true
file_finder.workspace = true
fs.workspace = true
@@ -20,16 +20,15 @@ use collections::VecDeque;
use debugger_ui::debugger_panel::DebugPanel;
use editor::ProposedChangesEditorToolbar;
use editor::{Editor, MultiBuffer, scroll::Autoscroll};
-use feature_flags::{DebuggerFeatureFlag, FeatureFlagViewExt};
use futures::future::Either;
use futures::{StreamExt, channel::mpsc, select_biased};
use git_ui::git_panel::GitPanel;
use git_ui::project_diff::ProjectDiffToolbar;
use gpui::{
- Action, App, AppContext as _, AsyncWindowContext, Context, DismissEvent, Element, Entity,
- Focusable, KeyBinding, ParentElement, PathPromptOptions, PromptLevel, ReadGlobal, SharedString,
- Styled, Task, TitlebarOptions, UpdateGlobal, Window, WindowKind, WindowOptions, actions,
- image_cache, point, px, retain_all,
+ Action, App, AppContext as _, Context, DismissEvent, Element, Entity, Focusable, KeyBinding,
+ ParentElement, PathPromptOptions, PromptLevel, ReadGlobal, SharedString, Styled, Task,
+ TitlebarOptions, UpdateGlobal, Window, WindowKind, WindowOptions, actions, image_cache, point,
+ px, retain_all,
};
use image_viewer::ImageInfo;
use migrate::{MigrationBanner, MigrationEvent, MigrationNotification, MigrationType};
@@ -480,6 +479,7 @@ fn initialize_panels(
workspace_handle.clone(),
cx.clone(),
);
+ let debug_panel = DebugPanel::load(workspace_handle.clone(), cx);
let (
project_panel,
@@ -489,6 +489,7 @@ fn initialize_panels(
channels_panel,
chat_panel,
notification_panel,
+ debug_panel,
) = futures::try_join!(
project_panel,
outline_panel,
@@ -497,6 +498,7 @@ fn initialize_panels(
channels_panel,
chat_panel,
notification_panel,
+ debug_panel,
)?;
workspace_handle.update_in(cx, |workspace, window, cx| {
@@ -507,20 +509,7 @@ fn initialize_panels(
workspace.add_panel(channels_panel, window, cx);
workspace.add_panel(chat_panel, window, cx);
workspace.add_panel(notification_panel, window, cx);
- cx.when_flag_enabled::<DebuggerFeatureFlag>(window, |_, window, cx| {
- cx.spawn_in(
- window,
- async move |workspace: gpui::WeakEntity<Workspace>,
- cx: &mut AsyncWindowContext| {
- let debug_panel = DebugPanel::load(workspace.clone(), cx).await?;
- workspace.update_in(cx, |workspace, window, cx| {
- workspace.add_panel(debug_panel, window, cx);
- })?;
- anyhow::Ok(())
- },
- )
- .detach()
- });
+ workspace.add_panel(debug_panel, window, cx);
})?;
let is_assistant2_enabled = !cfg!(test);