Detailed changes
@@ -1,3 +1,4 @@
+use feature_flags::{Debugger, FeatureFlagAppExt as _};
use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{
AnyElement, BackgroundExecutor, Entity, Focusable, FontWeight, ListSizingBehavior,
@@ -992,6 +993,17 @@ impl CodeActionsMenu {
.iter()
.skip(range.start)
.take(range.end - range.start)
+ .filter(|action| {
+ if action
+ .as_task()
+ .map(|task| matches!(task.task_type(), task::TaskType::Debug(_)))
+ .unwrap_or(false)
+ {
+ cx.has_flag::<Debugger>()
+ } else {
+ true
+ }
+ })
.enumerate()
.map(|(ix, action)| {
let item_ix = range.start + ix;
@@ -4798,6 +4798,8 @@ impl Editor {
Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
});
+ let debugger_flag = cx.has_flag::<Debugger>();
+
Some(cx.spawn_in(window, async move |editor, cx| {
let task_context = match task_context {
Some(task_context) => task_context.await,
@@ -4813,12 +4815,22 @@ impl Editor {
)),
})
});
- let spawn_straight_away = resolved_tasks
+ let spawn_straight_away = resolved_tasks.as_ref().map_or(false, |tasks| {
+ tasks
+ .templates
+ .iter()
+ .filter(|task| {
+ if matches!(task.1.task_type(), task::TaskType::Debug(_)) {
+ debugger_flag
+ } else {
+ true
+ }
+ })
+ .count()
+ == 1
+ }) && code_actions
.as_ref()
- .map_or(false, |tasks| tasks.templates.len() == 1)
- && code_actions
- .as_ref()
- .map_or(true, |actions| actions.is_empty());
+ .map_or(true, |actions| actions.is_empty());
if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
*editor.context_menu.borrow_mut() =
Some(CodeContextMenu::CodeActions(CodeActionsMenu {
@@ -6292,6 +6304,22 @@ impl Editor {
"Set Log Breakpoint"
};
+ let condition_breakpoint_msg =
+ if breakpoint.as_ref().is_some_and(|bp| bp.condition.is_some()) {
+ "Edit Condition Breakpoint"
+ } else {
+ "Set Condition Breakpoint"
+ };
+
+ let hit_condition_breakpoint_msg = if breakpoint
+ .as_ref()
+ .is_some_and(|bp| bp.hit_condition.is_some())
+ {
+ "Edit Hit Condition Breakpoint"
+ } else {
+ "Set Hit Condition Breakpoint"
+ };
+
let set_breakpoint_msg = if breakpoint.as_ref().is_some() {
"Unset Breakpoint"
} else {
@@ -6303,12 +6331,7 @@ impl Editor {
BreakpointState::Disabled => Some("Enable"),
});
- let breakpoint = breakpoint.unwrap_or_else(|| {
- Arc::new(Breakpoint {
- state: BreakpointState::Enabled,
- message: None,
- })
- });
+ let breakpoint = breakpoint.unwrap_or_else(|| Arc::new(Breakpoint::new_standard()));
ui::ContextMenu::build(window, cx, |menu, _, _cx| {
menu.on_blur_subscription(Subscription::new(|| {}))
@@ -6347,10 +6370,50 @@ impl Editor {
.log_err();
}
})
- .entry(log_breakpoint_msg, None, move |window, cx| {
+ .entry(log_breakpoint_msg, None, {
+ let breakpoint = breakpoint.clone();
+ let weak_editor = weak_editor.clone();
+ move |window, cx| {
+ weak_editor
+ .update(cx, |this, cx| {
+ this.add_edit_breakpoint_block(
+ anchor,
+ breakpoint.as_ref(),
+ BreakpointPromptEditAction::Log,
+ window,
+ cx,
+ );
+ })
+ .log_err();
+ }
+ })
+ .entry(condition_breakpoint_msg, None, {
+ let breakpoint = breakpoint.clone();
+ let weak_editor = weak_editor.clone();
+ move |window, cx| {
+ weak_editor
+ .update(cx, |this, cx| {
+ this.add_edit_breakpoint_block(
+ anchor,
+ breakpoint.as_ref(),
+ BreakpointPromptEditAction::Condition,
+ window,
+ cx,
+ );
+ })
+ .log_err();
+ }
+ })
+ .entry(hit_condition_breakpoint_msg, None, move |window, cx| {
weak_editor
.update(cx, |this, cx| {
- this.add_edit_breakpoint_block(anchor, breakpoint.as_ref(), window, cx);
+ this.add_edit_breakpoint_block(
+ anchor,
+ breakpoint.as_ref(),
+ BreakpointPromptEditAction::HitCondition,
+ window,
+ cx,
+ );
})
.log_err();
})
@@ -8597,12 +8660,20 @@ impl Editor {
&mut self,
anchor: Anchor,
breakpoint: &Breakpoint,
+ edit_action: BreakpointPromptEditAction,
window: &mut Window,
cx: &mut Context<Self>,
) {
let weak_editor = cx.weak_entity();
let bp_prompt = cx.new(|cx| {
- BreakpointPromptEditor::new(weak_editor, anchor, breakpoint.clone(), window, cx)
+ BreakpointPromptEditor::new(
+ weak_editor,
+ anchor,
+ breakpoint.clone(),
+ edit_action,
+ window,
+ cx,
+ )
});
let height = bp_prompt.update(cx, |this, cx| {
@@ -8721,11 +8792,13 @@ impl Editor {
Breakpoint {
message: None,
state: BreakpointState::Enabled,
+ condition: None,
+ hit_condition: None,
},
)
});
- self.add_edit_breakpoint_block(anchor, &bp, window, cx);
+ self.add_edit_breakpoint_block(anchor, &bp, BreakpointPromptEditAction::Log, window, cx);
}
pub fn enable_breakpoint(
@@ -19861,11 +19934,18 @@ impl Global for KillRing {}
const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
+enum BreakpointPromptEditAction {
+ Log,
+ Condition,
+ HitCondition,
+}
+
struct BreakpointPromptEditor {
pub(crate) prompt: Entity<Editor>,
editor: WeakEntity<Editor>,
breakpoint_anchor: Anchor,
breakpoint: Breakpoint,
+ edit_action: BreakpointPromptEditAction,
block_ids: HashSet<CustomBlockId>,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
_subscriptions: Vec<Subscription>,
@@ -19878,19 +19958,19 @@ impl BreakpointPromptEditor {
editor: WeakEntity<Editor>,
breakpoint_anchor: Anchor,
breakpoint: Breakpoint,
+ edit_action: BreakpointPromptEditAction,
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
- let buffer = cx.new(|cx| {
- Buffer::local(
- breakpoint
- .message
- .as_ref()
- .map(|msg| msg.to_string())
- .unwrap_or_default(),
- cx,
- )
- });
+ let base_text = match edit_action {
+ BreakpointPromptEditAction::Log => breakpoint.message.as_ref(),
+ BreakpointPromptEditAction::Condition => breakpoint.condition.as_ref(),
+ BreakpointPromptEditAction::HitCondition => breakpoint.hit_condition.as_ref(),
+ }
+ .map(|msg| msg.to_string())
+ .unwrap_or_default();
+
+ let buffer = cx.new(|cx| Buffer::local(base_text, cx));
let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
let prompt = cx.new(|cx| {
@@ -19906,7 +19986,11 @@ impl BreakpointPromptEditor {
prompt.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
prompt.set_show_cursor_when_unfocused(false, cx);
prompt.set_placeholder_text(
- "Message to log when breakpoint is hit. Expressions within {} are interpolated.",
+ match edit_action {
+ BreakpointPromptEditAction::Log => "Message to log when a breakpoint is hit. Expressions within {} are interpolated.",
+ BreakpointPromptEditAction::Condition => "Condition when a breakpoint is hit. Expressions within {} are interpolated.",
+ BreakpointPromptEditAction::HitCondition => "How many breakpoint hits to ignore",
+ },
cx,
);
@@ -19918,6 +20002,7 @@ impl BreakpointPromptEditor {
editor,
breakpoint_anchor,
breakpoint,
+ edit_action,
gutter_dimensions: Arc::new(Mutex::new(GutterDimensions::default())),
block_ids: Default::default(),
_subscriptions: vec![],
@@ -19930,7 +20015,7 @@ impl BreakpointPromptEditor {
fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
if let Some(editor) = self.editor.upgrade() {
- let log_message = self
+ let message = self
.prompt
.read(cx)
.buffer
@@ -19945,7 +20030,17 @@ impl BreakpointPromptEditor {
editor.edit_breakpoint_at_anchor(
self.breakpoint_anchor,
self.breakpoint.clone(),
- BreakpointEditAction::EditLogMessage(log_message.into()),
+ match self.edit_action {
+ BreakpointPromptEditAction::Log => {
+ BreakpointEditAction::EditLogMessage(message.into())
+ }
+ BreakpointPromptEditAction::Condition => {
+ BreakpointEditAction::EditCondition(message.into())
+ }
+ BreakpointPromptEditAction::HitCondition => {
+ BreakpointEditAction::EditHitCondition(message.into())
+ }
+ },
cx,
);
@@ -17387,6 +17387,8 @@ fn assert_breakpoint(
Breakpoint {
message: breakpoint.message.clone(),
state: breakpoint.state,
+ condition: breakpoint.condition.clone(),
+ hit_condition: breakpoint.hit_condition.clone(),
},
)
})
@@ -17415,13 +17417,7 @@ fn add_log_breakpoint_at_cursor(
.buffer_snapshot
.anchor_before(Point::new(cursor_position.row, 0));
- (
- breakpoint_position,
- Breakpoint {
- message: Some(Arc::from(log_message)),
- state: BreakpointState::Enabled,
- },
- )
+ (breakpoint_position, Breakpoint::new_log(&log_message))
});
editor.edit_breakpoint_at_anchor(
@@ -294,6 +294,60 @@ impl BreakpointStore {
})
}
}
+ BreakpointEditAction::EditHitCondition(hit_condition) => {
+ if !hit_condition.is_empty() {
+ let found_bp =
+ breakpoint_set
+ .breakpoints
+ .iter_mut()
+ .find_map(|(other_pos, other_bp)| {
+ if breakpoint.0 == *other_pos {
+ Some(other_bp)
+ } else {
+ None
+ }
+ });
+
+ if let Some(found_bp) = found_bp {
+ found_bp.hit_condition = Some(hit_condition.clone());
+ } else {
+ breakpoint.1.hit_condition = Some(hit_condition.clone());
+ // We did not remove any breakpoint, hence let's toggle one.
+ breakpoint_set.breakpoints.push(breakpoint.clone());
+ }
+ } else if breakpoint.1.hit_condition.is_some() {
+ breakpoint_set.breakpoints.retain(|(other_pos, other)| {
+ &breakpoint.0 != other_pos && other.hit_condition.is_none()
+ })
+ }
+ }
+ BreakpointEditAction::EditCondition(condition) => {
+ if !condition.is_empty() {
+ let found_bp =
+ breakpoint_set
+ .breakpoints
+ .iter_mut()
+ .find_map(|(other_pos, other_bp)| {
+ if breakpoint.0 == *other_pos {
+ Some(other_bp)
+ } else {
+ None
+ }
+ });
+
+ if let Some(found_bp) = found_bp {
+ found_bp.condition = Some(condition.clone());
+ } else {
+ breakpoint.1.condition = Some(condition.clone());
+ // We did not remove any breakpoint, hence let's toggle one.
+ breakpoint_set.breakpoints.push(breakpoint.clone());
+ }
+ } else if breakpoint.1.condition.is_some() {
+ breakpoint_set.breakpoints.retain(|(other_pos, other)| {
+ &breakpoint.0 != other_pos && other.condition.is_none()
+ })
+ }
+ }
}
if breakpoint_set.breakpoints.is_empty() {
@@ -424,6 +478,8 @@ impl BreakpointStore {
path: path.clone(),
state: breakpoint.state,
message: breakpoint.message.clone(),
+ condition: breakpoint.condition.clone(),
+ hit_condition: breakpoint.hit_condition.clone(),
}
})
.collect()
@@ -447,6 +503,8 @@ impl BreakpointStore {
path: path.clone(),
message: breakpoint.message.clone(),
state: breakpoint.state,
+ hit_condition: breakpoint.hit_condition.clone(),
+ condition: breakpoint.condition.clone(),
}
})
.collect(),
@@ -500,6 +558,8 @@ impl BreakpointStore {
Breakpoint {
message: bp.message,
state: bp.state,
+ condition: bp.condition,
+ hit_condition: bp.hit_condition,
},
))
}
@@ -537,13 +597,15 @@ pub enum BreakpointStoreEvent {
impl EventEmitter<BreakpointStoreEvent> for BreakpointStore {}
-type LogMessage = Arc<str>;
+type BreakpointMessage = Arc<str>;
#[derive(Clone, Debug)]
pub enum BreakpointEditAction {
Toggle,
InvertState,
- EditLogMessage(LogMessage),
+ EditLogMessage(BreakpointMessage),
+ EditCondition(BreakpointMessage),
+ EditHitCondition(BreakpointMessage),
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -574,7 +636,10 @@ impl BreakpointState {
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Breakpoint {
- pub message: Option<Arc<str>>,
+ pub message: Option<BreakpointMessage>,
+ /// How many times do we hit the breakpoint until we actually stop at it e.g. (2 = 2 times of the breakpoint action)
+ pub hit_condition: Option<BreakpointMessage>,
+ pub condition: Option<BreakpointMessage>,
pub state: BreakpointState,
}
@@ -582,6 +647,17 @@ impl Breakpoint {
pub fn new_standard() -> Self {
Self {
state: BreakpointState::Enabled,
+ hit_condition: None,
+ condition: None,
+ message: None,
+ }
+ }
+
+ pub fn new_condition(hit_condition: &str) -> Self {
+ Self {
+ state: BreakpointState::Enabled,
+ condition: None,
+ hit_condition: Some(hit_condition.into()),
message: None,
}
}
@@ -589,6 +665,8 @@ impl Breakpoint {
pub fn new_log(log_message: &str) -> Self {
Self {
state: BreakpointState::Enabled,
+ hit_condition: None,
+ condition: None,
message: Some(log_message.into()),
}
}
@@ -601,6 +679,11 @@ impl Breakpoint {
BreakpointState::Disabled => proto::BreakpointState::Disabled.into(),
},
message: self.message.as_ref().map(|s| String::from(s.as_ref())),
+ condition: self.condition.as_ref().map(|s| String::from(s.as_ref())),
+ hit_condition: self
+ .hit_condition
+ .as_ref()
+ .map(|s| String::from(s.as_ref())),
})
}
@@ -610,7 +693,9 @@ impl Breakpoint {
Some(proto::BreakpointState::Disabled) => BreakpointState::Disabled,
None | Some(proto::BreakpointState::Enabled) => BreakpointState::Enabled,
},
- message: breakpoint.message.map(|message| message.into()),
+ message: breakpoint.message.map(Into::into),
+ condition: breakpoint.condition.map(Into::into),
+ hit_condition: breakpoint.hit_condition.map(Into::into),
})
}
@@ -631,6 +716,8 @@ pub struct SourceBreakpoint {
pub row: u32,
pub path: Arc<Path>,
pub message: Option<Arc<str>>,
+ pub condition: Option<Arc<str>>,
+ pub hit_condition: Option<Arc<str>>,
pub state: BreakpointState,
}
@@ -639,8 +726,12 @@ impl From<SourceBreakpoint> for dap::SourceBreakpoint {
Self {
line: bp.row as u64 + 1,
column: None,
- condition: None,
- hit_condition: None,
+ condition: bp
+ .condition
+ .map(|condition| String::from(condition.as_ref())),
+ hit_condition: bp
+ .hit_condition
+ .map(|hit_condition| String::from(hit_condition.as_ref())),
log_message: bp.message.map(|message| String::from(message.as_ref())),
mode: None,
}
@@ -2673,6 +2673,8 @@ message Breakpoint {
BreakpointState state = 2;
reserved 3;
optional string message = 4;
+ optional string condition = 5;
+ optional string hit_condition = 6;
}
message BreakpointsForFile {
@@ -148,6 +148,8 @@ impl Column for SerializedWindowBounds {
pub struct Breakpoint {
pub position: u32,
pub message: Option<Arc<str>>,
+ pub condition: Option<Arc<str>>,
+ pub hit_condition: Option<Arc<str>>,
pub state: BreakpointState,
}
@@ -190,7 +192,8 @@ struct Breakpoints(Vec<Breakpoint>);
impl sqlez::bindable::StaticColumnCount for Breakpoint {
fn column_count() -> usize {
- 2 + BreakpointStateWrapper::column_count()
+ // Position, log message, condition message, and hit condition message
+ 4 + BreakpointStateWrapper::column_count()
}
}
@@ -202,6 +205,8 @@ impl sqlez::bindable::Bind for Breakpoint {
) -> anyhow::Result<i32> {
let next_index = statement.bind(&self.position, start_index)?;
let next_index = statement.bind(&self.message, next_index)?;
+ let next_index = statement.bind(&self.condition, next_index)?;
+ let next_index = statement.bind(&self.hit_condition, next_index)?;
statement.bind(
&BreakpointStateWrapper(Cow::Borrowed(&self.state)),
next_index,
@@ -216,12 +221,16 @@ impl Column for Breakpoint {
.with_context(|| format!("Failed to read BreakPoint at index {start_index}"))?
as u32;
let (message, next_index) = Option::<String>::column(statement, start_index + 1)?;
+ let (condition, next_index) = Option::<String>::column(statement, next_index)?;
+ let (hit_condition, next_index) = Option::<String>::column(statement, next_index)?;
let (state, next_index) = BreakpointStateWrapper::column(statement, next_index)?;
Ok((
Breakpoint {
position,
message: message.map(Arc::from),
+ condition: condition.map(Arc::from),
+ hit_condition: hit_condition.map(Arc::from),
state: state.0.into_owned(),
},
next_index,
@@ -527,7 +536,11 @@ define_connection! {
sql!(
ALTER TABLE breakpoints DROP COLUMN kind
),
- sql!(ALTER TABLE toolchains ADD COLUMN relative_worktree_path TEXT DEFAULT "" NOT NULL)
+ sql!(ALTER TABLE toolchains ADD COLUMN relative_worktree_path TEXT DEFAULT "" NOT NULL),
+ sql!(
+ ALTER TABLE breakpoints ADD COLUMN condition TEXT;
+ ALTER TABLE breakpoints ADD COLUMN hit_condition TEXT;
+ ),
];
}
@@ -680,7 +693,7 @@ impl WorkspaceDb {
fn breakpoints(&self, workspace_id: WorkspaceId) -> BTreeMap<Arc<Path>, Vec<SourceBreakpoint>> {
let breakpoints: Result<Vec<(PathBuf, Breakpoint)>> = self
.select_bound(sql! {
- SELECT path, breakpoint_location, log_message, state
+ SELECT path, breakpoint_location, log_message, condition, hit_condition, state
FROM breakpoints
WHERE workspace_id = ?
})
@@ -700,10 +713,20 @@ impl WorkspaceDb {
row: breakpoint.position,
path,
message: breakpoint.message,
+ condition: breakpoint.condition,
+ hit_condition: breakpoint.hit_condition,
state: breakpoint.state,
});
}
+ for (path, bps) in map.iter() {
+ log::debug!(
+ "Got {} breakpoints from path: {}",
+ bps.len(),
+ path.to_string_lossy()
+ );
+ }
+
map
}
Err(msg) => {
@@ -727,20 +750,23 @@ impl WorkspaceDb {
conn.exec_bound(sql!(DELETE FROM breakpoints WHERE workspace_id = ?1 AND path = ?2))?((workspace.id, path.as_ref()))
.context("Clearing old breakpoints")?;
for bp in breakpoints {
- let message = bp.message;
let state = BreakpointStateWrapper::from(bp.state);
match conn.exec_bound(sql!(
- INSERT INTO breakpoints (workspace_id, path, breakpoint_location, log_message, state)
- VALUES (?1, ?2, ?3, ?4, ?5);))?
+ INSERT INTO breakpoints (workspace_id, path, breakpoint_location, log_message, condition, hit_condition, state)
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);))?
((
workspace.id,
path.as_ref(),
bp.row,
- message,
+ bp.message,
+ bp.condition,
+ bp.hit_condition,
state,
)) {
- Ok(_) => {}
+ Ok(_) => {
+ log::debug!("Stored breakpoint at row: {} in path: {}", bp.row, path.to_string_lossy())
+ }
Err(err) => {
log::error!("{err}");
continue;
@@ -1409,18 +1435,40 @@ mod tests {
position: 123,
message: None,
state: BreakpointState::Enabled,
+ condition: None,
+ hit_condition: None,
};
let log_breakpoint = Breakpoint {
position: 456,
message: Some("Test log message".into()),
state: BreakpointState::Enabled,
+ condition: None,
+ hit_condition: None,
};
let disable_breakpoint = Breakpoint {
position: 578,
message: None,
state: BreakpointState::Disabled,
+ condition: None,
+ hit_condition: None,
+ };
+
+ let condition_breakpoint = Breakpoint {
+ position: 789,
+ message: None,
+ state: BreakpointState::Enabled,
+ condition: Some("x > 5".into()),
+ hit_condition: None,
+ };
+
+ let hit_condition_breakpoint = Breakpoint {
+ position: 999,
+ message: None,
+ state: BreakpointState::Enabled,
+ condition: None,
+ hit_condition: Some(">= 3".into()),
};
let workspace = SerializedWorkspace {
@@ -1441,18 +1489,40 @@ mod tests {
path: Arc::from(path),
message: breakpoint.message.clone(),
state: breakpoint.state,
+ condition: breakpoint.condition.clone(),
+ hit_condition: breakpoint.hit_condition.clone(),
},
SourceBreakpoint {
row: log_breakpoint.position,
path: Arc::from(path),
message: log_breakpoint.message.clone(),
state: log_breakpoint.state,
+ condition: log_breakpoint.condition.clone(),
+ hit_condition: log_breakpoint.hit_condition.clone(),
},
SourceBreakpoint {
row: disable_breakpoint.position,
path: Arc::from(path),
message: disable_breakpoint.message.clone(),
state: disable_breakpoint.state,
+ condition: disable_breakpoint.condition.clone(),
+ hit_condition: disable_breakpoint.hit_condition.clone(),
+ },
+ SourceBreakpoint {
+ row: condition_breakpoint.position,
+ path: Arc::from(path),
+ message: condition_breakpoint.message.clone(),
+ state: condition_breakpoint.state,
+ condition: condition_breakpoint.condition.clone(),
+ hit_condition: condition_breakpoint.hit_condition.clone(),
+ },
+ SourceBreakpoint {
+ row: hit_condition_breakpoint.position,
+ path: Arc::from(path),
+ message: hit_condition_breakpoint.message.clone(),
+ state: hit_condition_breakpoint.state,
+ condition: hit_condition_breakpoint.condition.clone(),
+ hit_condition: hit_condition_breakpoint.hit_condition.clone(),
},
],
);
@@ -1467,22 +1537,74 @@ mod tests {
let loaded = db.workspace_for_roots(&["/tmp"]).unwrap();
let loaded_breakpoints = loaded.breakpoints.get(&Arc::from(path)).unwrap();
- assert_eq!(loaded_breakpoints.len(), 3);
+ assert_eq!(loaded_breakpoints.len(), 5);
+ // normal breakpoint
assert_eq!(loaded_breakpoints[0].row, breakpoint.position);
assert_eq!(loaded_breakpoints[0].message, breakpoint.message);
+ assert_eq!(loaded_breakpoints[0].condition, breakpoint.condition);
+ assert_eq!(
+ loaded_breakpoints[0].hit_condition,
+ breakpoint.hit_condition
+ );
assert_eq!(loaded_breakpoints[0].state, breakpoint.state);
assert_eq!(loaded_breakpoints[0].path, Arc::from(path));
+ // enabled breakpoint
assert_eq!(loaded_breakpoints[1].row, log_breakpoint.position);
assert_eq!(loaded_breakpoints[1].message, log_breakpoint.message);
+ assert_eq!(loaded_breakpoints[1].condition, log_breakpoint.condition);
+ assert_eq!(
+ loaded_breakpoints[1].hit_condition,
+ log_breakpoint.hit_condition
+ );
assert_eq!(loaded_breakpoints[1].state, log_breakpoint.state);
assert_eq!(loaded_breakpoints[1].path, Arc::from(path));
+ // disable breakpoint
assert_eq!(loaded_breakpoints[2].row, disable_breakpoint.position);
assert_eq!(loaded_breakpoints[2].message, disable_breakpoint.message);
+ assert_eq!(
+ loaded_breakpoints[2].condition,
+ disable_breakpoint.condition
+ );
+ assert_eq!(
+ loaded_breakpoints[2].hit_condition,
+ disable_breakpoint.hit_condition
+ );
assert_eq!(loaded_breakpoints[2].state, disable_breakpoint.state);
assert_eq!(loaded_breakpoints[2].path, Arc::from(path));
+
+ // condition breakpoint
+ assert_eq!(loaded_breakpoints[3].row, condition_breakpoint.position);
+ assert_eq!(loaded_breakpoints[3].message, condition_breakpoint.message);
+ assert_eq!(
+ loaded_breakpoints[3].condition,
+ condition_breakpoint.condition
+ );
+ assert_eq!(
+ loaded_breakpoints[3].hit_condition,
+ condition_breakpoint.hit_condition
+ );
+ assert_eq!(loaded_breakpoints[3].state, condition_breakpoint.state);
+ assert_eq!(loaded_breakpoints[3].path, Arc::from(path));
+
+ // hit condition breakpoint
+ assert_eq!(loaded_breakpoints[4].row, hit_condition_breakpoint.position);
+ assert_eq!(
+ loaded_breakpoints[4].message,
+ hit_condition_breakpoint.message
+ );
+ assert_eq!(
+ loaded_breakpoints[4].condition,
+ hit_condition_breakpoint.condition
+ );
+ assert_eq!(
+ loaded_breakpoints[4].hit_condition,
+ hit_condition_breakpoint.hit_condition
+ );
+ assert_eq!(loaded_breakpoints[4].state, hit_condition_breakpoint.state);
+ assert_eq!(loaded_breakpoints[4].path, Arc::from(path));
}
#[gpui::test]