Uncomment persistence tests

Kirill Bulatov created

Change summary

crates/language2/src/syntax_map.rs                  |   2 
crates/semantic_index/src/semantic_index_tests.rs   |   8 
crates/workspace2/Cargo.toml                        |   6 
crates/workspace2/src/dock.rs                       |   6 
crates/workspace2/src/item.rs                       |  12 
crates/workspace2/src/notifications.rs              |   6 
crates/workspace2/src/pane.rs                       |   4 
crates/workspace2/src/pane/dragged_item_receiver.rs |   2 
crates/workspace2/src/pane_group.rs                 |   4 
crates/workspace2/src/persistence.rs                | 846 +++++++-------
crates/workspace2/src/persistence/model.rs          |  24 
crates/workspace2/src/searchable.rs                 |   2 
crates/workspace2/src/status_bar.rs                 |   2 
crates/workspace2/src/toolbar.rs                    |   2 
crates/workspace2/src/workspace2.rs                 |   4 
crates/workspace2/src/workspace_settings.rs         |   2 
crates/zed2/src/zed2.rs                             |  63 
17 files changed, 495 insertions(+), 500 deletions(-)

Detailed changes

crates/language2/src/syntax_map.rs 🔗

@@ -234,7 +234,6 @@ impl SyntaxMap {
         self.snapshot.interpolate(text);
     }
 
-    #[allow(dead_code)] // todo!()
     #[cfg(test)]
     pub fn reparse(&mut self, language: Arc<Language>, text: &BufferSnapshot) {
         self.snapshot
@@ -786,7 +785,6 @@ impl SyntaxSnapshot {
         )
     }
 
-    #[allow(dead_code)] // todo!()
     #[cfg(test)]
     pub fn layers<'a>(&'a self, buffer: &'a BufferSnapshot) -> Vec<SyntaxLayerInfo> {
         self.layers_for_range(0..buffer.len(), buffer).collect()

crates/semantic_index/src/semantic_index_tests.rs 🔗

@@ -289,12 +289,12 @@ async fn test_code_context_retrieval_rust() {
         impl E {
             // This is also a preceding comment
             pub fn function_1() -> Option<()> {
-                todo!();
+                unimplemented!();
             }
 
             // This is a preceding comment
             fn function_2() -> Result<()> {
-                todo!();
+                unimplemented!();
             }
         }
 
@@ -344,7 +344,7 @@ async fn test_code_context_retrieval_rust() {
                 "
                 // This is also a preceding comment
                 pub fn function_1() -> Option<()> {
-                    todo!();
+                    unimplemented!();
                 }"
                 .unindent(),
                 text.find("pub fn function_1").unwrap(),
@@ -353,7 +353,7 @@ async fn test_code_context_retrieval_rust() {
                 "
                 // This is a preceding comment
                 fn function_2() -> Result<()> {
-                    todo!();
+                    unimplemented!();
                 }"
                 .unindent(),
                 text.find("fn function_2").unwrap(),

crates/workspace2/Cargo.toml 🔗

@@ -14,7 +14,7 @@ test-support = [
     "client2/test-support",
     "project2/test-support",
     "settings2/test-support",
-    "gpui2/test-support",
+    "gpui/test-support",
     "fs2/test-support"
 ]
 
@@ -25,7 +25,7 @@ client2 = { path = "../client2" }
 collections = { path = "../collections" }
 # context_menu = { path = "../context_menu" }
 fs2 = { path = "../fs2" }
-gpui2 = { path = "../gpui2" }
+gpui = { package = "gpui2", path = "../gpui2" }
 install_cli2 = { path = "../install_cli2" }
 language2 = { path = "../language2" }
 #menu = { path = "../menu" }
@@ -56,7 +56,7 @@ uuid.workspace = true
 [dev-dependencies]
 call2 = { path = "../call2", features = ["test-support"] }
 client2 = { path = "../client2", features = ["test-support"] }
-gpui2 = { path = "../gpui2", features = ["test-support"] }
+gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
 project2 = { path = "../project2", features = ["test-support"] }
 settings2 = { path = "../settings2", features = ["test-support"] }
 fs2 = { path = "../fs2", features = ["test-support"] }

crates/workspace2/src/dock.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{status_bar::StatusItemView, Axis, Workspace};
-use gpui2::{
+use gpui::{
     div, Action, AnyView, AppContext, Div, Entity, EntityId, EventEmitter, ParentElement, Render,
     Subscription, View, ViewContext, WeakView, WindowContext,
 };
@@ -629,7 +629,7 @@ impl StatusItemView for PanelButtons {
 #[cfg(any(test, feature = "test-support"))]
 pub mod test {
     use super::*;
-    use gpui2::{div, Div, ViewContext, WindowContext};
+    use gpui::{div, Div, ViewContext, WindowContext};
 
     #[derive(Debug)]
     pub enum TestPanelEvent {
@@ -678,7 +678,7 @@ pub mod test {
             "TestPanel"
         }
 
-        fn position(&self, _: &gpui2::WindowContext) -> super::DockPosition {
+        fn position(&self, _: &gpui::WindowContext) -> super::DockPosition {
             self.position
         }
 

crates/workspace2/src/item.rs 🔗

@@ -11,7 +11,7 @@ use client2::{
     proto::{self, PeerId},
     Client,
 };
-use gpui2::{
+use gpui::{
     AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, HighlightStyle, Model, Pixels,
     Point, Render, SharedString, Task, View, ViewContext, WeakView, WindowContext,
 };
@@ -212,7 +212,7 @@ pub trait ItemHandle: 'static + Send {
         &self,
         cx: &mut WindowContext,
         handler: Box<dyn Fn(ItemEvent, &mut WindowContext) + Send>,
-    ) -> gpui2::Subscription;
+    ) -> gpui::Subscription;
     fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>;
     fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>;
     fn tab_content(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<Pane>;
@@ -256,7 +256,7 @@ pub trait ItemHandle: 'static + Send {
         &mut self,
         cx: &mut AppContext,
         callback: Box<dyn FnOnce(&mut AppContext) + Send>,
-    ) -> gpui2::Subscription;
+    ) -> gpui::Subscription;
     fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
     fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
     fn breadcrumbs(&self, theme: &ThemeVariant, cx: &AppContext) -> Option<Vec<BreadcrumbText>>;
@@ -286,7 +286,7 @@ impl<T: Item> ItemHandle for View<T> {
         &self,
         cx: &mut WindowContext,
         handler: Box<dyn Fn(ItemEvent, &mut WindowContext) + Send>,
-    ) -> gpui2::Subscription {
+    ) -> gpui::Subscription {
         cx.subscribe(self, move |_, event, cx| {
             for item_event in T::to_item_events(event) {
                 handler(item_event, cx)
@@ -573,7 +573,7 @@ impl<T: Item> ItemHandle for View<T> {
         &mut self,
         cx: &mut AppContext,
         callback: Box<dyn FnOnce(&mut AppContext) + Send>,
-    ) -> gpui2::Subscription {
+    ) -> gpui::Subscription {
         cx.observe_release(self, move |_, cx| callback(cx))
     }
 
@@ -747,7 +747,7 @@ impl<T: FollowableItem> FollowableItemHandle for View<T> {
 // pub mod test {
 //     use super::{Item, ItemEvent};
 //     use crate::{ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId};
-//     use gpui2::{
+//     use gpui::{
 //         elements::Empty, AnyElement, AppContext, Element, Entity, Model, Task, View,
 //         ViewContext, View, WeakViewHandle,
 //     };

crates/workspace2/src/notifications.rs 🔗

@@ -1,6 +1,6 @@
 use crate::{Toast, Workspace};
 use collections::HashMap;
-use gpui2::{AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext};
+use gpui::{AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext};
 use std::{any::TypeId, ops::DerefMut};
 
 pub fn init(cx: &mut AppContext) {
@@ -160,7 +160,7 @@ impl Workspace {
 
 pub mod simple_message_notification {
     use super::Notification;
-    use gpui2::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
+    use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext};
     use serde::Deserialize;
     use std::{borrow::Cow, sync::Arc};
 
@@ -265,7 +265,7 @@ pub mod simple_message_notification {
     //             "MessageNotification"
     //         }
 
-    //         fn render(&mut self, cx: &mut gpui2::ViewContext<Self>) -> gpui::AnyElement<Self> {
+    //         fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> gpui::AnyElement<Self> {
     //             let theme = theme2::current(cx).clone();
     //             let theme = &theme.simple_message_notification;
 

crates/workspace2/src/pane.rs 🔗

@@ -8,7 +8,7 @@ use crate::{
 };
 use anyhow::Result;
 use collections::{HashMap, HashSet, VecDeque};
-use gpui2::{
+use gpui::{
     AppContext, AsyncWindowContext, Component, Div, EntityId, EventEmitter, Model, PromptLevel,
     Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
 };
@@ -2907,6 +2907,6 @@ impl Render for DraggedTab {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
-        div().w_8().h_4().bg(gpui2::red())
+        div().w_8().h_4().bg(gpui::red())
     }
 }

crates/workspace2/src/pane/dragged_item_receiver.rs 🔗

@@ -1,6 +1,6 @@
 use super::DraggedItem;
 use crate::{Pane, SplitDirection, Workspace};
-use gpui2::{
+use gpui::{
     color::Color,
     elements::{Canvas, MouseEventHandler, ParentElement, Stack},
     geometry::{rect::RectF, vector::Vector2F},

crates/workspace2/src/pane_group.rs 🔗

@@ -6,9 +6,7 @@ use db2::sqlez::{
     bindable::{Bind, Column, StaticColumnCount},
     statement::Statement,
 };
-use gpui2::{
-    point, size, AnyElement, AnyWeakView, Bounds, Model, Pixels, Point, View, ViewContext,
-};
+use gpui::{point, size, AnyElement, AnyWeakView, Bounds, Model, Pixels, Point, View, ViewContext};
 use parking_lot::Mutex;
 use project2::Project;
 use serde::Deserialize;

crates/workspace2/src/persistence.rs 🔗

@@ -6,7 +6,7 @@ use std::path::Path;
 
 use anyhow::{anyhow, bail, Context, Result};
 use db2::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
-use gpui2::WindowBounds;
+use gpui::WindowBounds;
 
 use util::{unzip_option, ResultExt};
 use uuid::Uuid;
@@ -549,425 +549,425 @@ impl WorkspaceDb {
     }
 }
 
-// todo!()
-// #[cfg(test)]
-// mod tests {
-//     use super::*;
-//     use db::open_test_db;
-
-//     #[gpui::test]
-//     async fn test_next_id_stability() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("test_next_id_stability").await);
-
-//         db.write(|conn| {
-//             conn.migrate(
-//                 "test_table",
-//                 &[sql!(
-//                     CREATE TABLE test_table(
-//                         text TEXT,
-//                         workspace_id INTEGER,
-//                         FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
-//                         ON DELETE CASCADE
-//                     ) STRICT;
-//                 )],
-//             )
-//             .unwrap();
-//         })
-//         .await;
-
-//         let id = db.next_id().await.unwrap();
-//         // Assert the empty row got inserted
-//         assert_eq!(
-//             Some(id),
-//             db.select_row_bound::<WorkspaceId, WorkspaceId>(sql!(
-//                 SELECT workspace_id FROM workspaces WHERE workspace_id = ?
-//             ))
-//             .unwrap()(id)
-//             .unwrap()
-//         );
-
-//         db.write(move |conn| {
-//             conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
-//                 .unwrap()(("test-text-1", id))
-//             .unwrap()
-//         })
-//         .await;
-
-//         let test_text_1 = db
-//             .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
-//             .unwrap()(1)
-//         .unwrap()
-//         .unwrap();
-//         assert_eq!(test_text_1, "test-text-1");
-//     }
-
-//     #[gpui::test]
-//     async fn test_workspace_id_stability() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("test_workspace_id_stability").await);
-
-//         db.write(|conn| {
-//             conn.migrate(
-//                 "test_table",
-//                 &[sql!(
-//                     CREATE TABLE test_table(
-//                         text TEXT,
-//                         workspace_id INTEGER,
-//                         FOREIGN KEY(workspace_id)
-//                             REFERENCES workspaces(workspace_id)
-//                         ON DELETE CASCADE
-//                     ) STRICT;)],
-//             )
-//         })
-//         .await
-//         .unwrap();
-
-//         let mut workspace_1 = SerializedWorkspace {
-//             id: 1,
-//             location: (["/tmp", "/tmp2"]).into(),
-//             center_group: Default::default(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         let workspace_2 = SerializedWorkspace {
-//             id: 2,
-//             location: (["/tmp"]).into(),
-//             center_group: Default::default(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         db.save_workspace(workspace_1.clone()).await;
-
-//         db.write(|conn| {
-//             conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
-//                 .unwrap()(("test-text-1", 1))
-//             .unwrap();
-//         })
-//         .await;
-
-//         db.save_workspace(workspace_2.clone()).await;
-
-//         db.write(|conn| {
-//             conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
-//                 .unwrap()(("test-text-2", 2))
-//             .unwrap();
-//         })
-//         .await;
-
-//         workspace_1.location = (["/tmp", "/tmp3"]).into();
-//         db.save_workspace(workspace_1.clone()).await;
-//         db.save_workspace(workspace_1).await;
-//         db.save_workspace(workspace_2).await;
-
-//         let test_text_2 = db
-//             .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
-//             .unwrap()(2)
-//         .unwrap()
-//         .unwrap();
-//         assert_eq!(test_text_2, "test-text-2");
-
-//         let test_text_1 = db
-//             .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
-//             .unwrap()(1)
-//         .unwrap()
-//         .unwrap();
-//         assert_eq!(test_text_1, "test-text-1");
-//     }
-
-//     fn group(axis: gpui::Axis, children: Vec<SerializedPaneGroup>) -> SerializedPaneGroup {
-//         SerializedPaneGroup::Group {
-//             axis,
-//             flexes: None,
-//             children,
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_full_workspace_serialization() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("test_full_workspace_serialization").await);
-
-//         //  -----------------
-//         //  | 1,2   | 5,6   |
-//         //  | - - - |       |
-//         //  | 3,4   |       |
-//         //  -----------------
-//         let center_group = group(
-//             gpui::Axis::Horizontal,
-//             vec![
-//                 group(
-//                     gpui::Axis::Vertical,
-//                     vec![
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 5, false),
-//                                 SerializedItem::new("Terminal", 6, true),
-//                             ],
-//                             false,
-//                         )),
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 7, true),
-//                                 SerializedItem::new("Terminal", 8, false),
-//                             ],
-//                             false,
-//                         )),
-//                     ],
-//                 ),
-//                 SerializedPaneGroup::Pane(SerializedPane::new(
-//                     vec![
-//                         SerializedItem::new("Terminal", 9, false),
-//                         SerializedItem::new("Terminal", 10, true),
-//                     ],
-//                     false,
-//                 )),
-//             ],
-//         );
-
-//         let workspace = SerializedWorkspace {
-//             id: 5,
-//             location: (["/tmp", "/tmp2"]).into(),
-//             center_group,
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         db.save_workspace(workspace.clone()).await;
-//         let round_trip_workspace = db.workspace_for_roots(&["/tmp2", "/tmp"]);
-
-//         assert_eq!(workspace, round_trip_workspace.unwrap());
-
-//         // Test guaranteed duplicate IDs
-//         db.save_workspace(workspace.clone()).await;
-//         db.save_workspace(workspace.clone()).await;
-
-//         let round_trip_workspace = db.workspace_for_roots(&["/tmp", "/tmp2"]);
-//         assert_eq!(workspace, round_trip_workspace.unwrap());
-//     }
-
-//     #[gpui::test]
-//     async fn test_workspace_assignment() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("test_basic_functionality").await);
-
-//         let workspace_1 = SerializedWorkspace {
-//             id: 1,
-//             location: (["/tmp", "/tmp2"]).into(),
-//             center_group: Default::default(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         let mut workspace_2 = SerializedWorkspace {
-//             id: 2,
-//             location: (["/tmp"]).into(),
-//             center_group: Default::default(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         db.save_workspace(workspace_1.clone()).await;
-//         db.save_workspace(workspace_2.clone()).await;
-
-//         // Test that paths are treated as a set
-//         assert_eq!(
-//             db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
-//             workspace_1
-//         );
-//         assert_eq!(
-//             db.workspace_for_roots(&["/tmp2", "/tmp"]).unwrap(),
-//             workspace_1
-//         );
-
-//         // Make sure that other keys work
-//         assert_eq!(db.workspace_for_roots(&["/tmp"]).unwrap(), workspace_2);
-//         assert_eq!(db.workspace_for_roots(&["/tmp3", "/tmp2", "/tmp4"]), None);
-
-//         // Test 'mutate' case of updating a pre-existing id
-//         workspace_2.location = (["/tmp", "/tmp2"]).into();
-
-//         db.save_workspace(workspace_2.clone()).await;
-//         assert_eq!(
-//             db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
-//             workspace_2
-//         );
-
-//         // Test other mechanism for mutating
-//         let mut workspace_3 = SerializedWorkspace {
-//             id: 3,
-//             location: (&["/tmp", "/tmp2"]).into(),
-//             center_group: Default::default(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         };
-
-//         db.save_workspace(workspace_3.clone()).await;
-//         assert_eq!(
-//             db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
-//             workspace_3
-//         );
-
-//         // Make sure that updating paths differently also works
-//         workspace_3.location = (["/tmp3", "/tmp4", "/tmp2"]).into();
-//         db.save_workspace(workspace_3.clone()).await;
-//         assert_eq!(db.workspace_for_roots(&["/tmp2", "tmp"]), None);
-//         assert_eq!(
-//             db.workspace_for_roots(&["/tmp2", "/tmp3", "/tmp4"])
-//                 .unwrap(),
-//             workspace_3
-//         );
-//     }
-
-//     use crate::persistence::model::SerializedWorkspace;
-//     use crate::persistence::model::{SerializedItem, SerializedPane, SerializedPaneGroup};
-
-//     fn default_workspace<P: AsRef<Path>>(
-//         workspace_id: &[P],
-//         center_group: &SerializedPaneGroup,
-//     ) -> SerializedWorkspace {
-//         SerializedWorkspace {
-//             id: 4,
-//             location: workspace_id.into(),
-//             center_group: center_group.clone(),
-//             bounds: Default::default(),
-//             display: Default::default(),
-//             docks: Default::default(),
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_simple_split() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("simple_split").await);
-
-//         //  -----------------
-//         //  | 1,2   | 5,6   |
-//         //  | - - - |       |
-//         //  | 3,4   |       |
-//         //  -----------------
-//         let center_pane = group(
-//             gpui::Axis::Horizontal,
-//             vec![
-//                 group(
-//                     gpui::Axis::Vertical,
-//                     vec![
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 1, false),
-//                                 SerializedItem::new("Terminal", 2, true),
-//                             ],
-//                             false,
-//                         )),
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 4, false),
-//                                 SerializedItem::new("Terminal", 3, true),
-//                             ],
-//                             true,
-//                         )),
-//                     ],
-//                 ),
-//                 SerializedPaneGroup::Pane(SerializedPane::new(
-//                     vec![
-//                         SerializedItem::new("Terminal", 5, true),
-//                         SerializedItem::new("Terminal", 6, false),
-//                     ],
-//                     false,
-//                 )),
-//             ],
-//         );
-
-//         let workspace = default_workspace(&["/tmp"], &center_pane);
-
-//         db.save_workspace(workspace.clone()).await;
-
-//         let new_workspace = db.workspace_for_roots(&["/tmp"]).unwrap();
-
-//         assert_eq!(workspace.center_group, new_workspace.center_group);
-//     }
-
-//     #[gpui::test]
-//     async fn test_cleanup_panes() {
-//         env_logger::try_init().ok();
-
-//         let db = WorkspaceDb(open_test_db("test_cleanup_panes").await);
-
-//         let center_pane = group(
-//             gpui::Axis::Horizontal,
-//             vec![
-//                 group(
-//                     gpui::Axis::Vertical,
-//                     vec![
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 1, false),
-//                                 SerializedItem::new("Terminal", 2, true),
-//                             ],
-//                             false,
-//                         )),
-//                         SerializedPaneGroup::Pane(SerializedPane::new(
-//                             vec![
-//                                 SerializedItem::new("Terminal", 4, false),
-//                                 SerializedItem::new("Terminal", 3, true),
-//                             ],
-//                             true,
-//                         )),
-//                     ],
-//                 ),
-//                 SerializedPaneGroup::Pane(SerializedPane::new(
-//                     vec![
-//                         SerializedItem::new("Terminal", 5, false),
-//                         SerializedItem::new("Terminal", 6, true),
-//                     ],
-//                     false,
-//                 )),
-//             ],
-//         );
-
-//         let id = &["/tmp"];
-
-//         let mut workspace = default_workspace(id, &center_pane);
-
-//         db.save_workspace(workspace.clone()).await;
-
-//         workspace.center_group = group(
-//             gpui::Axis::Vertical,
-//             vec![
-//                 SerializedPaneGroup::Pane(SerializedPane::new(
-//                     vec![
-//                         SerializedItem::new("Terminal", 1, false),
-//                         SerializedItem::new("Terminal", 2, true),
-//                     ],
-//                     false,
-//                 )),
-//                 SerializedPaneGroup::Pane(SerializedPane::new(
-//                     vec![
-//                         SerializedItem::new("Terminal", 4, true),
-//                         SerializedItem::new("Terminal", 3, false),
-//                     ],
-//                     true,
-//                 )),
-//             ],
-//         );
-
-//         db.save_workspace(workspace.clone()).await;
-
-//         let new_workspace = db.workspace_for_roots(id).unwrap();
-
-//         assert_eq!(workspace.center_group, new_workspace.center_group);
-//     }
-// }
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use db2::open_test_db;
+    use gpui;
+
+    #[gpui::test]
+    async fn test_next_id_stability() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("test_next_id_stability").await);
+
+        db.write(|conn| {
+            conn.migrate(
+                "test_table",
+                &[sql!(
+                    CREATE TABLE test_table(
+                        text TEXT,
+                        workspace_id INTEGER,
+                        FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
+                        ON DELETE CASCADE
+                    ) STRICT;
+                )],
+            )
+            .unwrap();
+        })
+        .await;
+
+        let id = db.next_id().await.unwrap();
+        // Assert the empty row got inserted
+        assert_eq!(
+            Some(id),
+            db.select_row_bound::<WorkspaceId, WorkspaceId>(sql!(
+                SELECT workspace_id FROM workspaces WHERE workspace_id = ?
+            ))
+            .unwrap()(id)
+            .unwrap()
+        );
+
+        db.write(move |conn| {
+            conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
+                .unwrap()(("test-text-1", id))
+            .unwrap()
+        })
+        .await;
+
+        let test_text_1 = db
+            .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
+            .unwrap()(1)
+        .unwrap()
+        .unwrap();
+        assert_eq!(test_text_1, "test-text-1");
+    }
+
+    #[gpui::test]
+    async fn test_workspace_id_stability() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("test_workspace_id_stability").await);
+
+        db.write(|conn| {
+            conn.migrate(
+                "test_table",
+                &[sql!(
+                        CREATE TABLE test_table(
+                            text TEXT,
+                            workspace_id INTEGER,
+                            FOREIGN KEY(workspace_id)
+                                REFERENCES workspaces(workspace_id)
+                            ON DELETE CASCADE
+                        ) STRICT;)],
+            )
+        })
+        .await
+        .unwrap();
+
+        let mut workspace_1 = SerializedWorkspace {
+            id: 1,
+            location: (["/tmp", "/tmp2"]).into(),
+            center_group: Default::default(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        let workspace_2 = SerializedWorkspace {
+            id: 2,
+            location: (["/tmp"]).into(),
+            center_group: Default::default(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        db.save_workspace(workspace_1.clone()).await;
+
+        db.write(|conn| {
+            conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
+                .unwrap()(("test-text-1", 1))
+            .unwrap();
+        })
+        .await;
+
+        db.save_workspace(workspace_2.clone()).await;
+
+        db.write(|conn| {
+            conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
+                .unwrap()(("test-text-2", 2))
+            .unwrap();
+        })
+        .await;
+
+        workspace_1.location = (["/tmp", "/tmp3"]).into();
+        db.save_workspace(workspace_1.clone()).await;
+        db.save_workspace(workspace_1).await;
+        db.save_workspace(workspace_2).await;
+
+        let test_text_2 = db
+            .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
+            .unwrap()(2)
+        .unwrap()
+        .unwrap();
+        assert_eq!(test_text_2, "test-text-2");
+
+        let test_text_1 = db
+            .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
+            .unwrap()(1)
+        .unwrap()
+        .unwrap();
+        assert_eq!(test_text_1, "test-text-1");
+    }
+
+    fn group(axis: Axis, children: Vec<SerializedPaneGroup>) -> SerializedPaneGroup {
+        SerializedPaneGroup::Group {
+            axis,
+            flexes: None,
+            children,
+        }
+    }
+
+    #[gpui::test]
+    async fn test_full_workspace_serialization() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("test_full_workspace_serialization").await);
+
+        //  -----------------
+        //  | 1,2   | 5,6   |
+        //  | - - - |       |
+        //  | 3,4   |       |
+        //  -----------------
+        let center_group = group(
+            Axis::Horizontal,
+            vec![
+                group(
+                    Axis::Vertical,
+                    vec![
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 5, false),
+                                SerializedItem::new("Terminal", 6, true),
+                            ],
+                            false,
+                        )),
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 7, true),
+                                SerializedItem::new("Terminal", 8, false),
+                            ],
+                            false,
+                        )),
+                    ],
+                ),
+                SerializedPaneGroup::Pane(SerializedPane::new(
+                    vec![
+                        SerializedItem::new("Terminal", 9, false),
+                        SerializedItem::new("Terminal", 10, true),
+                    ],
+                    false,
+                )),
+            ],
+        );
+
+        let workspace = SerializedWorkspace {
+            id: 5,
+            location: (["/tmp", "/tmp2"]).into(),
+            center_group,
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        db.save_workspace(workspace.clone()).await;
+        let round_trip_workspace = db.workspace_for_roots(&["/tmp2", "/tmp"]);
+
+        assert_eq!(workspace, round_trip_workspace.unwrap());
+
+        // Test guaranteed duplicate IDs
+        db.save_workspace(workspace.clone()).await;
+        db.save_workspace(workspace.clone()).await;
+
+        let round_trip_workspace = db.workspace_for_roots(&["/tmp", "/tmp2"]);
+        assert_eq!(workspace, round_trip_workspace.unwrap());
+    }
+
+    #[gpui::test]
+    async fn test_workspace_assignment() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("test_basic_functionality").await);
+
+        let workspace_1 = SerializedWorkspace {
+            id: 1,
+            location: (["/tmp", "/tmp2"]).into(),
+            center_group: Default::default(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        let mut workspace_2 = SerializedWorkspace {
+            id: 2,
+            location: (["/tmp"]).into(),
+            center_group: Default::default(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        db.save_workspace(workspace_1.clone()).await;
+        db.save_workspace(workspace_2.clone()).await;
+
+        // Test that paths are treated as a set
+        assert_eq!(
+            db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
+            workspace_1
+        );
+        assert_eq!(
+            db.workspace_for_roots(&["/tmp2", "/tmp"]).unwrap(),
+            workspace_1
+        );
+
+        // Make sure that other keys work
+        assert_eq!(db.workspace_for_roots(&["/tmp"]).unwrap(), workspace_2);
+        assert_eq!(db.workspace_for_roots(&["/tmp3", "/tmp2", "/tmp4"]), None);
+
+        // Test 'mutate' case of updating a pre-existing id
+        workspace_2.location = (["/tmp", "/tmp2"]).into();
+
+        db.save_workspace(workspace_2.clone()).await;
+        assert_eq!(
+            db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
+            workspace_2
+        );
+
+        // Test other mechanism for mutating
+        let mut workspace_3 = SerializedWorkspace {
+            id: 3,
+            location: (&["/tmp", "/tmp2"]).into(),
+            center_group: Default::default(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        };
+
+        db.save_workspace(workspace_3.clone()).await;
+        assert_eq!(
+            db.workspace_for_roots(&["/tmp", "/tmp2"]).unwrap(),
+            workspace_3
+        );
+
+        // Make sure that updating paths differently also works
+        workspace_3.location = (["/tmp3", "/tmp4", "/tmp2"]).into();
+        db.save_workspace(workspace_3.clone()).await;
+        assert_eq!(db.workspace_for_roots(&["/tmp2", "tmp"]), None);
+        assert_eq!(
+            db.workspace_for_roots(&["/tmp2", "/tmp3", "/tmp4"])
+                .unwrap(),
+            workspace_3
+        );
+    }
+
+    use crate::persistence::model::SerializedWorkspace;
+    use crate::persistence::model::{SerializedItem, SerializedPane, SerializedPaneGroup};
+
+    fn default_workspace<P: AsRef<Path>>(
+        workspace_id: &[P],
+        center_group: &SerializedPaneGroup,
+    ) -> SerializedWorkspace {
+        SerializedWorkspace {
+            id: 4,
+            location: workspace_id.into(),
+            center_group: center_group.clone(),
+            bounds: Default::default(),
+            display: Default::default(),
+            docks: Default::default(),
+        }
+    }
+
+    #[gpui::test]
+    async fn test_simple_split() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("simple_split").await);
+
+        //  -----------------
+        //  | 1,2   | 5,6   |
+        //  | - - - |       |
+        //  | 3,4   |       |
+        //  -----------------
+        let center_pane = group(
+            Axis::Horizontal,
+            vec![
+                group(
+                    Axis::Vertical,
+                    vec![
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 1, false),
+                                SerializedItem::new("Terminal", 2, true),
+                            ],
+                            false,
+                        )),
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 4, false),
+                                SerializedItem::new("Terminal", 3, true),
+                            ],
+                            true,
+                        )),
+                    ],
+                ),
+                SerializedPaneGroup::Pane(SerializedPane::new(
+                    vec![
+                        SerializedItem::new("Terminal", 5, true),
+                        SerializedItem::new("Terminal", 6, false),
+                    ],
+                    false,
+                )),
+            ],
+        );
+
+        let workspace = default_workspace(&["/tmp"], &center_pane);
+
+        db.save_workspace(workspace.clone()).await;
+
+        let new_workspace = db.workspace_for_roots(&["/tmp"]).unwrap();
+
+        assert_eq!(workspace.center_group, new_workspace.center_group);
+    }
+
+    #[gpui::test]
+    async fn test_cleanup_panes() {
+        env_logger::try_init().ok();
+
+        let db = WorkspaceDb(open_test_db("test_cleanup_panes").await);
+
+        let center_pane = group(
+            Axis::Horizontal,
+            vec![
+                group(
+                    Axis::Vertical,
+                    vec![
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 1, false),
+                                SerializedItem::new("Terminal", 2, true),
+                            ],
+                            false,
+                        )),
+                        SerializedPaneGroup::Pane(SerializedPane::new(
+                            vec![
+                                SerializedItem::new("Terminal", 4, false),
+                                SerializedItem::new("Terminal", 3, true),
+                            ],
+                            true,
+                        )),
+                    ],
+                ),
+                SerializedPaneGroup::Pane(SerializedPane::new(
+                    vec![
+                        SerializedItem::new("Terminal", 5, false),
+                        SerializedItem::new("Terminal", 6, true),
+                    ],
+                    false,
+                )),
+            ],
+        );
+
+        let id = &["/tmp"];
+
+        let mut workspace = default_workspace(id, &center_pane);
+
+        db.save_workspace(workspace.clone()).await;
+
+        workspace.center_group = group(
+            Axis::Vertical,
+            vec![
+                SerializedPaneGroup::Pane(SerializedPane::new(
+                    vec![
+                        SerializedItem::new("Terminal", 1, false),
+                        SerializedItem::new("Terminal", 2, true),
+                    ],
+                    false,
+                )),
+                SerializedPaneGroup::Pane(SerializedPane::new(
+                    vec![
+                        SerializedItem::new("Terminal", 4, true),
+                        SerializedItem::new("Terminal", 3, false),
+                    ],
+                    true,
+                )),
+            ],
+        );
+
+        db.save_workspace(workspace.clone()).await;
+
+        let new_workspace = db.workspace_for_roots(id).unwrap();
+
+        assert_eq!(workspace.center_group, new_workspace.center_group);
+    }
+}

crates/workspace2/src/persistence/model.rs 🔗

@@ -7,7 +7,7 @@ use db2::sqlez::{
     bindable::{Bind, Column, StaticColumnCount},
     statement::Statement,
 };
-use gpui2::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
+use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
 use project2::Project;
 use std::{
     path::{Path, PathBuf},
@@ -55,7 +55,7 @@ impl Column for WorkspaceLocation {
     }
 }
 
-#[derive(PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone)]
 pub struct SerializedWorkspace {
     pub id: WorkspaceId,
     pub location: WorkspaceLocation,
@@ -127,7 +127,7 @@ impl Bind for DockData {
     }
 }
 
-#[derive(PartialEq, Clone)]
+#[derive(Debug, PartialEq, Clone)]
 pub enum SerializedPaneGroup {
     Group {
         axis: Axis,
@@ -286,15 +286,15 @@ pub struct SerializedItem {
     pub active: bool,
 }
 
-// impl SerializedItem {
-//     pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
-//         Self {
-//             kind: Arc::from(kind.as_ref()),
-//             item_id,
-//             active,
-//         }
-//     }
-// }
+impl SerializedItem {
+    pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
+        Self {
+            kind: Arc::from(kind.as_ref()),
+            item_id,
+            active,
+        }
+    }
+}
 
 #[cfg(test)]
 impl Default for SerializedItem {

crates/workspace2/src/searchable.rs 🔗

@@ -1,6 +1,6 @@
 use std::{any::Any, sync::Arc};
 
-use gpui2::{AnyView, AppContext, Subscription, Task, View, ViewContext, WindowContext};
+use gpui::{AnyView, AppContext, Subscription, Task, View, ViewContext, WindowContext};
 use project2::search::SearchQuery;
 
 use crate::{

crates/workspace2/src/status_bar.rs 🔗

@@ -1,7 +1,7 @@
 use std::any::TypeId;
 
 use crate::{ItemHandle, Pane};
-use gpui2::{
+use gpui::{
     div, AnyView, Component, Div, ParentElement, Render, Styled, Subscription, View, ViewContext,
     WindowContext,
 };

crates/workspace2/src/toolbar.rs 🔗

@@ -1,5 +1,5 @@
 use crate::ItemHandle;
-use gpui2::{
+use gpui::{
     AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext,
 };
 

crates/workspace2/src/workspace2.rs 🔗

@@ -30,7 +30,7 @@ use futures::{
     future::try_join_all,
     Future, FutureExt, StreamExt,
 };
-use gpui2::{
+use gpui::{
     div, point, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext,
     AsyncWindowContext, Bounds, Component, Div, EntityId, EventEmitter, GlobalPixels, Model,
     ModelContext, ParentElement, Point, Render, Size, StatefulInteractive, Styled, Subscription,
@@ -460,7 +460,7 @@ struct Follower {
 impl AppState {
     #[cfg(any(test, feature = "test-support"))]
     pub fn test(cx: &mut AppContext) -> Arc<Self> {
-        use gpui2::Context;
+        use gpui::Context;
         use node_runtime::FakeNodeRuntime;
         use settings2::SettingsStore;
 

crates/workspace2/src/workspace_settings.rs 🔗

@@ -49,7 +49,7 @@ impl Settings for WorkspaceSettings {
     fn load(
         default_value: &Self::FileContent,
         user_values: &[&Self::FileContent],
-        _: &mut gpui2::AppContext,
+        _: &mut gpui::AppContext,
     ) -> anyhow::Result<Self> {
         Self::load_via_json_merge(default_value, user_values)
     }

crates/zed2/src/zed2.rs 🔗

@@ -69,11 +69,10 @@ pub async fn handle_cli_connection(
                 let mut caret_positions = HashMap::default();
 
                 let paths = if paths.is_empty() {
-                    todo!()
-                    //     workspace::last_opened_workspace_paths()
-                    //         .await
-                    //         .map(|location| location.paths().to_vec())
-                    //         .unwrap_or_default()
+                    workspace2::last_opened_workspace_paths()
+                        .await
+                        .map(|location| location.paths().to_vec())
+                        .unwrap_or_default()
                 } else {
                     paths
                         .into_iter()
@@ -260,33 +259,33 @@ pub fn initialize_workspace(
                 move |workspace, _, event, cx| {
                     if let workspace2::Event::PaneAdded(pane) = event {
                         pane.update(cx, |pane, cx| {
-                            // todo!()
-                            // pane.toolbar().update(cx, |toolbar, cx| {
-                            //     let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace));
-                            //     toolbar.add_item(breadcrumbs, cx);
-                            //     let buffer_search_bar = cx.add_view(BufferSearchBar::new);
-                            //     toolbar.add_item(buffer_search_bar.clone(), cx);
-                            //     let quick_action_bar = cx.add_view(|_| {
-                            //         QuickActionBar::new(buffer_search_bar, workspace)
-                            //     });
-                            //     toolbar.add_item(quick_action_bar, cx);
-                            //     let diagnostic_editor_controls =
-                            //         cx.add_view(|_| diagnostics2::ToolbarControls::new());
-                            //     toolbar.add_item(diagnostic_editor_controls, cx);
-                            //     let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
-                            //     toolbar.add_item(project_search_bar, cx);
-                            //     let submit_feedback_button =
-                            //         cx.add_view(|_| SubmitFeedbackButton::new());
-                            //     toolbar.add_item(submit_feedback_button, cx);
-                            //     let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new());
-                            //     toolbar.add_item(feedback_info_text, cx);
-                            //     let lsp_log_item =
-                            //         cx.add_view(|_| language_tools::LspLogToolbarItemView::new());
-                            //     toolbar.add_item(lsp_log_item, cx);
-                            //     let syntax_tree_item = cx
-                            //         .add_view(|_| language_tools::SyntaxTreeToolbarItemView::new());
-                            //     toolbar.add_item(syntax_tree_item, cx);
-                            // })
+                            pane.toolbar().update(cx, |toolbar, cx| {
+                                // todo!()
+                                //     let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace));
+                                //     toolbar.add_item(breadcrumbs, cx);
+                                //     let buffer_search_bar = cx.add_view(BufferSearchBar::new);
+                                //     toolbar.add_item(buffer_search_bar.clone(), cx);
+                                //     let quick_action_bar = cx.add_view(|_| {
+                                //         QuickActionBar::new(buffer_search_bar, workspace)
+                                //     });
+                                //     toolbar.add_item(quick_action_bar, cx);
+                                //     let diagnostic_editor_controls =
+                                //         cx.add_view(|_| diagnostics2::ToolbarControls::new());
+                                //     toolbar.add_item(diagnostic_editor_controls, cx);
+                                //     let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
+                                //     toolbar.add_item(project_search_bar, cx);
+                                //     let submit_feedback_button =
+                                //         cx.add_view(|_| SubmitFeedbackButton::new());
+                                //     toolbar.add_item(submit_feedback_button, cx);
+                                //     let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new());
+                                //     toolbar.add_item(feedback_info_text, cx);
+                                //     let lsp_log_item =
+                                //         cx.add_view(|_| language_tools::LspLogToolbarItemView::new());
+                                //     toolbar.add_item(lsp_log_item, cx);
+                                //     let syntax_tree_item = cx
+                                //         .add_view(|_| language_tools::SyntaxTreeToolbarItemView::new());
+                                //     toolbar.add_item(syntax_tree_item, cx);
+                            })
                         });
                     }
                 }