From ecaef8dac345cc11b74b4dc95c75c818f91fee5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 12:11:23 +0200 Subject: [PATCH 001/140] WIP start adding component::Kind enum --- app/gui/src/controller/searcher/component.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index d166e0dabd4d..4b791e654faf 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -30,6 +30,7 @@ pub type Id = suggestion_database::entry::Id; /// Information how the component matches the filtering pattern. pub type MatchInfo = controller::searcher::action::MatchInfo; +pub type Virtual = controller::searcher::action::hardcoded::Suggestion; // ============== @@ -81,6 +82,22 @@ pub enum Order { +// ============ +// === Kind === +// ============ + +pub enum Kind { + FromDb { + id: Immutable, + suggestion: Rc, + }, + Virtual { + suggestion: Rc, + }, +} + + + // ================= // === Component === // ================= From f3cf705ffa1072065daae11438fc2bef07afefec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 12:42:40 +0200 Subject: [PATCH 002/140] WIP --- app/gui/src/controller/searcher/component.rs | 3 +-- app/gui/src/controller/searcher/component/builder.rs | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 4b791e654faf..b25070c0e787 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -113,8 +113,7 @@ pub enum Kind { #[allow(missing_docs)] #[derive(Clone, CloneRef, Debug)] pub struct Component { - pub id: Immutable, - pub suggestion: Rc, + pub kind: Kind, pub match_info: Rc>, } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index fcb7c766017e..0dc9658bdbdb 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -118,7 +118,9 @@ impl List { let lookup_component_by_id = |id| Some(Component::new(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { - self.allowed_favorites.insert(*component.id); + if let component::Kind::FromDb { id, .. } = component.kind { + self.allowed_favorites.insert(*id); + } let mut component_inserted_somewhere = false; if let Some(parent_module) = component.suggestion.parent_module() { if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { From b7cfc59e87fbc9fa82340f99446b1e43886c0ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:17:09 +0200 Subject: [PATCH 003/140] WIP extend_... --- .../controller/searcher/component/builder.rs | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 0dc9658bdbdb..dcb253b4a03c 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -118,30 +118,33 @@ impl List { let lookup_component_by_id = |id| Some(Component::new(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { - if let component::Kind::FromDb { id, .. } = component.kind { + if let component::Kind::FromDb { id, suggestion } = component.kind { self.allowed_favorites.insert(*id); - } - let mut component_inserted_somewhere = false; - if let Some(parent_module) = component.suggestion.parent_module() { - if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { - parent_group.content.entries.borrow_mut().push(component.clone_ref()); - component_inserted_somewhere = true; - let parent_id = parent_group.content.component_id; - let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); - let not_module = component.suggestion.kind != Kind::Module; - if in_local_scope && not_module { - self.local_scope.entries.borrow_mut().push(component.clone_ref()); - } - } - if let Some(top_group) = self.lookup_module_group(db, &parent_module.top_module()) { - if let Some(flatten_group) = &mut top_group.flattened_content { - flatten_group.entries.borrow_mut().push(component.clone_ref()); + let mut component_inserted_somewhere = false; + if let Some(parent_module) = suggestion.parent_module() { + if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { + parent_group.content.entries.borrow_mut().push(component.clone_ref()); component_inserted_somewhere = true; + let parent_id = parent_group.content.component_id; + let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); + let not_module = suggestion.kind != Kind::Module; + if in_local_scope && not_module { + self.local_scope.entries.borrow_mut().push(component.clone_ref()); + } + } + let top_module = parent_module.top_module(); + if let Some(top_group) = self.lookup_module_group(db, &top_module) { + if let Some(flatten_group) = &mut top_group.flattened_content { + flatten_group.entries.borrow_mut().push(component.clone_ref()); + component_inserted_somewhere = true; + } } } - } - if component_inserted_somewhere { - self.all_components.push(component); + if component_inserted_somewhere { + self.all_components.push(component); + } + } else { + event!(ERROR, "The suggestion database returned a component of a non-FromDb kind: {component:?}"); } } } From 239fa388391433bfbd4a0aa9779d9fa0baa337f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:20:33 +0200 Subject: [PATCH 004/140] WIP constr. & retain --- app/gui/src/controller/searcher/component.rs | 3 ++- app/gui/src/controller/searcher/component/builder.rs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index b25070c0e787..b79892641953 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -122,7 +122,8 @@ impl Component { /// /// The matching info will be filled for an empty pattern. pub fn new(id: Id, suggestion: Rc) -> Self { - Self { id: Immutable(id), suggestion, match_info: default() } + let kind = Kind::FromDb { id: Immutable(id), suggestion }; + Self { kind, match_info: default() } } /// The label which should be displayed in the Component Browser. diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index dcb253b4a03c..a5b88a50f1f4 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -220,7 +220,10 @@ impl List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); for group in favorites_groups.iter_mut() { - group.retain_entries(|e| self.allowed_favorites.contains(&e.id)); + group.retain_entries(|e| match e.kind { + component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), + component::Kind::Virtual { .. } => true, + }); self.all_components.extend(group.entries.borrow().iter().cloned()); } component::group::List::new(favorites_groups) From f7a53c58ed69fd3f9421baa0419847831d957e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:25:32 +0200 Subject: [PATCH 005/140] WIP can_be_entered & Display --- app/gui/src/controller/searcher/component.rs | 28 +++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index b79892641953..bd6bb7081ce3 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -141,7 +141,11 @@ impl Component { /// Currently, only modules can be entered, and then the Browser should display content and /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { - self.suggestion.kind == suggestion_database::entry::Kind::Module + if let Kind::FromDb { suggestion, .. } = self.kind { + suggestion.kind == suggestion_database::entry::Kind::Module + } else { + false + } } /// Update matching info. @@ -163,14 +167,20 @@ impl Component { impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let self_type_not_here = - self.suggestion.self_type.as_ref().filter(|t| *t != &self.suggestion.module); - if let Some(self_type) = self_type_not_here { - let self_name = self_type.name.from_case(Case::Snake).to_case(Case::Title); - let name = self.suggestion.name.from_case(Case::Snake).to_case(Case::Lower); - write!(f, "{} {}", self_name, name) - } else { - write!(f, "{}", self.suggestion.name.from_case(Case::Snake).to_case(Case::Lower)) + match self.kind { + Kind::FromDb { suggestion, .. } => { + let self_type_not_here = + suggestion.self_type.as_ref().filter(|t| *t != &suggestion.module); + if let Some(self_type) = self_type_not_here { + let self_name = self_type.name.from_case(Case::Snake).to_case(Case::Title); + let name = suggestion.name.from_case(Case::Snake).to_case(Case::Lower); + write!(f, "{} {}", self_name, name) + } else { + write!(f, "{}", suggestion.name.from_case(Case::Snake).to_case(Case::Lower)) + } + }, + // FIXME[MC] + Kind::Virtual { .. } => write!(f, "FIXME"), } } } From 3868756bffe76339e39cf61728e46a7482941837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:43:39 +0200 Subject: [PATCH 006/140] WIP provider --- app/gui/src/presenter/searcher/provider.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index 7abf36b102e4..a444dcc4468e 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::controller::searcher::action::MatchInfo; +use crate::controller::searcher::component; use crate::model::suggestion_database; use enso_text as text; @@ -199,9 +200,22 @@ impl list_view::entry::ModelProvider for Component let match_info = component.match_info.borrow(); let label = component.label(); let highlighted = bytes_of_matched_letters(&*match_info, &label); - let kind = component.suggestion.kind; + let icon = match component.kind { + component::Kind::FromDb { suggestion, .. } => { + let kind = suggestion.kind; + for_each_kind_variant!(kind_to_icon(kind)) + }, + component::Kind::Virtual { suggestion } => { + let icon = suggestion.icon; + let parsed_icon = component_group_view::icon::Id::from_str(&icon); + parsed_icon.unwrap_or_else(|_| { + event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); + default() + }) + }, + }; Some(component_group_view::entry::Model { - icon: for_each_kind_variant!(kind_to_icon(kind)), + icon, highlighted_text: list_view::entry::GlyphHighlightedLabelModel { label, highlighted }, }) } From b5a565d5ab11a3a8bed29ad7d68fa708db8a61e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:57:45 +0200 Subject: [PATCH 007/140] WIP searcher --- app/gui/src/presenter/searcher.rs | 55 ++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index ed6157b9737a..581aac3fae97 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -4,6 +4,7 @@ use crate::prelude::*; use crate::controller::searcher::action::Suggestion; +use crate::controller::searcher::component; use crate::controller::searcher::Notification; use crate::controller::searcher::UserAction; use crate::executor::global::spawn_stream_handler; @@ -97,7 +98,12 @@ impl Model { ) -> Option<(ViewNodeId, node_view::Expression)> { let component = self.component_by_view_id(id); let new_code = component.and_then(|component| { - let suggestion = Suggestion::FromDatabase(component.suggestion.clone_ref()); + let suggestion = match component.kind { + component::Kind::FromDb { suggestion, .. } => + Suggestion::FromDatabase(suggestion.clone_ref()), + component::Kind::Virtual { suggestion } => + Suggestion::Hardcoded(suggestion.clone_ref()), + }; self.controller.use_suggestion(suggestion) }); match new_code { @@ -157,24 +163,35 @@ impl Model { ) -> String { let component = id.and_then(|id| self.component_by_view_id(id).ok()); if let Some(component) = component { - if let Some(documentation) = &component.suggestion.documentation_html { - let title = match component.suggestion.kind { - Kind::Atom => format!("Atom {}", component.suggestion.name), - Kind::Function => format!("Function {}", component.suggestion.name), - Kind::Local => format!("Node {}", component.suggestion.name), - Kind::Method => format!( - "Method {}{}{}", - component.suggestion.name, - if component.suggestion.self_type.is_some() { " of " } else { "" }, - component.suggestion.self_type.as_ref().map_or("", |tp| &tp.name), - ), - Kind::Module => format!("Module {}", component.suggestion.name), - }; - format!("

{title}

{documentation}") - } else { - provider::Action::doc_placeholder_for(&Suggestion::FromDatabase( - component.suggestion.clone_ref(), - )) + match component.kind { + component::Kind::FromDb { suggestion, .. } => { + if let Some(documentation) = &suggestion.documentation_html { + let title = match suggestion.kind { + Kind::Atom => format!("Atom {}", suggestion.name), + Kind::Function => format!("Function {}", suggestion.name), + Kind::Local => format!("Node {}", suggestion.name), + Kind::Method => format!( + "Method {}{}{}", + suggestion.name, + if suggestion.self_type.is_some() { " of " } else { "" }, + suggestion.self_type.as_ref().map_or("", |tp| &tp.name), + ), + Kind::Module => format!("Module {}", suggestion.name), + }; + format!("

{title}

{documentation}") + } else { + provider::Action::doc_placeholder_for(&Suggestion::FromDatabase( + suggestion.clone_ref(), + )) + } + }, + component::Kind::Virtual { suggestion } => { + if let Some(documentation) = &suggestion.documentation_html { + documentation.to_string() + } else { + default() + } + }, } } else { default() From ed5de9fd8fcfbbcbaff4c8c58d24cc75406167a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 16:58:52 +0200 Subject: [PATCH 008/140] WIP derive --- app/gui/src/controller/searcher/component.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index bd6bb7081ce3..4b00879a0903 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -86,6 +86,7 @@ pub enum Order { // === Kind === // ============ +#[derive(Clone, CloneRef, Debug)] pub enum Kind { FromDb { id: Immutable, From fd6d9eac40b7f34da3ad0c56df04643bee2df14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 17:01:15 +0200 Subject: [PATCH 009/140] add some missing borrows --- app/gui/src/controller/searcher/component.rs | 4 ++-- app/gui/src/controller/searcher/component/builder.rs | 2 +- app/gui/src/presenter/searcher/provider.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 4b00879a0903..b8a594d3e33f 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -142,7 +142,7 @@ impl Component { /// Currently, only modules can be entered, and then the Browser should display content and /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { - if let Kind::FromDb { suggestion, .. } = self.kind { + if let Kind::FromDb { suggestion, .. } = &self.kind { suggestion.kind == suggestion_database::entry::Kind::Module } else { false @@ -168,7 +168,7 @@ impl Component { impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { + match &self.kind { Kind::FromDb { suggestion, .. } => { let self_type_not_here = suggestion.self_type.as_ref().filter(|t| *t != &suggestion.module); diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index a5b88a50f1f4..8526d45d01ab 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -118,7 +118,7 @@ impl List { let lookup_component_by_id = |id| Some(Component::new(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { - if let component::Kind::FromDb { id, suggestion } = component.kind { + if let component::Kind::FromDb { id, ref suggestion } = component.kind { self.allowed_favorites.insert(*id); let mut component_inserted_somewhere = false; if let Some(parent_module) = suggestion.parent_module() { diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index a444dcc4468e..6aeb94c25c48 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -206,7 +206,7 @@ impl list_view::entry::ModelProvider for Component for_each_kind_variant!(kind_to_icon(kind)) }, component::Kind::Virtual { suggestion } => { - let icon = suggestion.icon; + let icon = &suggestion.icon; let parsed_icon = component_group_view::icon::Id::from_str(&icon); parsed_icon.unwrap_or_else(|_| { event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); From fa94e59777d05ee9cfda409a536e65d95463e706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 17:38:40 +0200 Subject: [PATCH 010/140] draft vgroup --- .../controller/searcher/component/builder.rs | 21 +++++++++++++++++++ .../controller/searcher/component/group.rs | 16 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 8526d45d01ab..49aecb93f283 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -219,6 +219,27 @@ impl List { fn build_favorites_and_add_to_all_components(&mut self) -> component::group::List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); + // FIXME[MC]: do it explicitly from searcher through a separate method + // TODO(LATER): how to make it possible to add virtual entries only to Standard.Base.Input + // group, not to any group named `Input`? + { + let vgroup = component::Group::from_name_and_virtual_entries("Favs", [ + Rc::new(component::Virtual { + name: "text input", + code: "\"\"", + this_arg: None, + argument_types: vec![], + // FIXME[MC] + return_type: None, + imports: vec![], + documentation_html: Some("This will allow you to enter some text easily."), + method_id: None, + // FIXME[MC] possible to fix? + icon: "TextInput".into(), + }), + ]); + favorites_groups.insert(0, vgroup); + } for group in favorites_groups.iter_mut() { group.retain_entries(|e| match e.kind { component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index b49186609d00..c96f5d4758d9 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -96,6 +96,22 @@ impl Group { Self::from_name_and_id(name, Some(component_id)) } + pub fn from_name_and_virtual_entries(name: impl Into, entries: impl IntoIterator>) -> Self { + let components = entries.into_iter().map(|suggestion| Component { + kind: component::Kind::Virtual { suggestion }, + match_info: default(), + }).collect_vec(); + let group_data = Data { + name: name.into(), + color: None, + component_id: None, + matched_items: Cell::new(components.len()), + initial_entries_order: components.clone(), + entries: RefCell::new(components), + }; + Group { data: Rc::new(group_data) } + } + /// Construct from [`execution_context::ComponentGroup`] components looked up in the suggestion /// database by their full qualified name. Returns a group containing only the successfully /// looked up components, or [`None`] if none of the components were found in the suggestion From f78979e0ffb7cb10e1df48b9c5d6388e90305a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 18:05:07 +0200 Subject: [PATCH 011/140] Display --- app/gui/src/controller/searcher/component.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index b8a594d3e33f..a2480eba29d7 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -180,8 +180,7 @@ impl Display for Component { write!(f, "{}", suggestion.name.from_case(Case::Snake).to_case(Case::Lower)) } }, - // FIXME[MC] - Kind::Virtual { .. } => write!(f, "FIXME"), + Kind::Virtual { suggestion } => write!(f, "{}", suggestion.name), } } } From f087d8d524f4b45a40b5e086985d70ef80b0668e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 27 Jul 2022 18:37:47 +0200 Subject: [PATCH 012/140] number input --- .../src/controller/searcher/component/builder.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 49aecb93f283..23104d15df1c 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -237,6 +237,19 @@ impl List { // FIXME[MC] possible to fix? icon: "TextInput".into(), }), + Rc::new(component::Virtual { + name: "number input", + code: "0", + this_arg: None, + argument_types: vec![], + // FIXME[MC] + return_type: None, + imports: vec![], + documentation_html: Some("This will allow you to enter a number easily."), + method_id: None, + // FIXME[MC] possible to fix? + icon: "NumberInput".into(), + }), ]); favorites_groups.insert(0, vgroup); } From 2fd6f6e7975f4541776ca70c489f9633d1397918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 12:53:31 +0200 Subject: [PATCH 013/140] cargo fmt --- app/gui/src/controller/searcher/component.rs | 13 +++---- .../controller/searcher/component/builder.rs | 35 ++++++++++--------- .../controller/searcher/component/group.rs | 26 ++++++++------ app/gui/src/presenter/searcher.rs | 10 +++--- app/gui/src/presenter/searcher/provider.rs | 4 +-- 5 files changed, 46 insertions(+), 42 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index a2480eba29d7..4f586159bf09 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -88,13 +88,8 @@ pub enum Order { #[derive(Clone, CloneRef, Debug)] pub enum Kind { - FromDb { - id: Immutable, - suggestion: Rc, - }, - Virtual { - suggestion: Rc, - }, + FromDb { id: Immutable, suggestion: Rc }, + Virtual { suggestion: Rc }, } @@ -114,7 +109,7 @@ pub enum Kind { #[allow(missing_docs)] #[derive(Clone, CloneRef, Debug)] pub struct Component { - pub kind: Kind, + pub kind: Kind, pub match_info: Rc>, } @@ -179,7 +174,7 @@ impl Display for Component { } else { write!(f, "{}", suggestion.name.from_case(Case::Snake).to_case(Case::Lower)) } - }, + } Kind::Virtual { suggestion } => write!(f, "{}", suggestion.name), } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 23104d15df1c..db3804df783e 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -126,7 +126,8 @@ impl List { parent_group.content.entries.borrow_mut().push(component.clone_ref()); component_inserted_somewhere = true; let parent_id = parent_group.content.component_id; - let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); + let in_local_scope = + parent_id == local_scope_id && local_scope_id.is_some(); let not_module = suggestion.kind != Kind::Module; if in_local_scope && not_module { self.local_scope.entries.borrow_mut().push(component.clone_ref()); @@ -225,30 +226,30 @@ impl List { { let vgroup = component::Group::from_name_and_virtual_entries("Favs", [ Rc::new(component::Virtual { - name: "text input", - code: "\"\"", - this_arg: None, - argument_types: vec![], + name: "text input", + code: "\"\"", + this_arg: None, + argument_types: vec![], // FIXME[MC] - return_type: None, - imports: vec![], + return_type: None, + imports: vec![], documentation_html: Some("This will allow you to enter some text easily."), - method_id: None, + method_id: None, // FIXME[MC] possible to fix? - icon: "TextInput".into(), + icon: "TextInput".into(), }), Rc::new(component::Virtual { - name: "number input", - code: "0", - this_arg: None, - argument_types: vec![], + name: "number input", + code: "0", + this_arg: None, + argument_types: vec![], // FIXME[MC] - return_type: None, - imports: vec![], + return_type: None, + imports: vec![], documentation_html: Some("This will allow you to enter a number easily."), - method_id: None, + method_id: None, // FIXME[MC] possible to fix? - icon: "NumberInput".into(), + icon: "NumberInput".into(), }), ]); favorites_groups.insert(0, vgroup); diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index c96f5d4758d9..81b3bbe61844 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -96,18 +96,24 @@ impl Group { Self::from_name_and_id(name, Some(component_id)) } - pub fn from_name_and_virtual_entries(name: impl Into, entries: impl IntoIterator>) -> Self { - let components = entries.into_iter().map(|suggestion| Component { - kind: component::Kind::Virtual { suggestion }, - match_info: default(), - }).collect_vec(); + pub fn from_name_and_virtual_entries( + name: impl Into, + entries: impl IntoIterator>, + ) -> Self { + let components = entries + .into_iter() + .map(|suggestion| Component { + kind: component::Kind::Virtual { suggestion }, + match_info: default(), + }) + .collect_vec(); let group_data = Data { - name: name.into(), - color: None, - component_id: None, - matched_items: Cell::new(components.len()), + name: name.into(), + color: None, + component_id: None, + matched_items: Cell::new(components.len()), initial_entries_order: components.clone(), - entries: RefCell::new(components), + entries: RefCell::new(components), }; Group { data: Rc::new(group_data) } } diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 581aac3fae97..6ad946c5c8cc 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -99,7 +99,7 @@ impl Model { let component = self.component_by_view_id(id); let new_code = component.and_then(|component| { let suggestion = match component.kind { - component::Kind::FromDb { suggestion, .. } => + component::Kind::FromDb { suggestion, .. } => Suggestion::FromDatabase(suggestion.clone_ref()), component::Kind::Virtual { suggestion } => Suggestion::Hardcoded(suggestion.clone_ref()), @@ -178,20 +178,22 @@ impl Model { ), Kind::Module => format!("Module {}", suggestion.name), }; - format!("

{title}

{documentation}") + format!( + "

{title}

{documentation}" + ) } else { provider::Action::doc_placeholder_for(&Suggestion::FromDatabase( suggestion.clone_ref(), )) } - }, + } component::Kind::Virtual { suggestion } => { if let Some(documentation) = &suggestion.documentation_html { documentation.to_string() } else { default() } - }, + } } } else { default() diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index 6aeb94c25c48..1961feb4f5c8 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -204,7 +204,7 @@ impl list_view::entry::ModelProvider for Component component::Kind::FromDb { suggestion, .. } => { let kind = suggestion.kind; for_each_kind_variant!(kind_to_icon(kind)) - }, + } component::Kind::Virtual { suggestion } => { let icon = &suggestion.icon; let parsed_icon = component_group_view::icon::Id::from_str(&icon); @@ -212,7 +212,7 @@ impl list_view::entry::ModelProvider for Component event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); default() }) - }, + } }; Some(component_group_view::entry::Model { icon, From 4a05df1301075f17e3dd1f24e0c1e4c5535dd81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 12:53:41 +0200 Subject: [PATCH 014/140] WIP ComponentGroup.library --- app/gui/src/model/execution_context.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/gui/src/model/execution_context.rs b/app/gui/src/model/execution_context.rs index 53ad8827c88d..b12696cf7589 100644 --- a/app/gui/src/model/execution_context.rs +++ b/app/gui/src/model/execution_context.rs @@ -6,6 +6,7 @@ use crate::model::module::QualifiedName as ModuleQualifiedName; use crate::model::suggestion_database::entry as suggestion; use crate::notification::Publisher; +use double_representation::project; use engine_protocol::language_server; use engine_protocol::language_server::ExpressionUpdate; use engine_protocol::language_server::ExpressionUpdatePayload; @@ -287,6 +288,10 @@ pub struct AttachedVisualization { #[allow(missing_docs)] #[derive(Clone, Debug, PartialEq)] pub struct ComponentGroup { + /// The fully qualified library name. + pub library: project::QualifiedName, + /// The group name without the library name prefix. E.g. given the `Standard.Base.Group 1` + /// group reference, the `name` field contains `Group 1`. pub name: ImString, /// An optional color to use when displaying the component group. pub color: Option, @@ -297,11 +302,12 @@ impl ComponentGroup { /// Construct from a [`language_server::LibraryComponentGroup`]. pub fn from_language_server_protocol_struct( group: language_server::LibraryComponentGroup, - ) -> Self { + ) -> FallibleResult { + let library = group.library.try_into()?; let name = group.name.into(); let color = group.color.as_ref().and_then(|c| color::Rgb::from_css_hex(c)); let components = group.exports.into_iter().map(|e| e.name.into()).collect(); - ComponentGroup { name, color, components } + ComponentGroup { library, name, color, components } } } From feae78e6e7869b77529a2a141e48ae6aa35ee5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 14:52:12 +0200 Subject: [PATCH 015/140] filter_map in ec::synchronized --- app/gui/src/model/execution_context.rs | 8 +++++--- .../src/model/execution_context/synchronized.rs | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/gui/src/model/execution_context.rs b/app/gui/src/model/execution_context.rs index b12696cf7589..f5a9aaa5e742 100644 --- a/app/gui/src/model/execution_context.rs +++ b/app/gui/src/model/execution_context.rs @@ -307,12 +307,14 @@ impl ComponentGroup { let name = group.name.into(); let color = group.color.as_ref().and_then(|c| color::Rgb::from_css_hex(c)); let components = group.exports.into_iter().map(|e| e.name.into()).collect(); - ComponentGroup { library, name, color, components } + Ok(ComponentGroup { library, name, color, components }) } } -impl From for ComponentGroup { - fn from(group: language_server::LibraryComponentGroup) -> Self { +impl TryFrom for ComponentGroup { + type Error = failure::Error; + + fn try_from(group: language_server::LibraryComponentGroup) -> FallibleResult { Self::from_language_server_protocol_struct(group) } } diff --git a/app/gui/src/model/execution_context/synchronized.rs b/app/gui/src/model/execution_context/synchronized.rs index b0186a2bf2d9..09474c7ffe46 100644 --- a/app/gui/src/model/execution_context/synchronized.rs +++ b/app/gui/src/model/execution_context/synchronized.rs @@ -102,7 +102,22 @@ impl ExecutionContext { match self.language_server.get_component_groups(&self.id).await { Ok(ls_response) => { let ls_groups = ls_response.component_groups; - let groups = ls_groups.into_iter().map(|group| group.into()).collect(); + let groups = ls_groups + .into_iter() + .filter_map(|group| match group.try_into() { + // TODO[MC] consider replacing with: .inspect_err(...).ok() + Ok(g) => Some(g), + Err(err) => { + let msg = iformat!( + "Failed to parse a component group returned by the Engine. The group \ + will not appear in the Favorites section of the Component Browser. \ + Error: {err}" + ); + error!(self.logger, "{msg}"); + None + } + }) + .collect(); *self.model.component_groups.borrow_mut() = Rc::new(groups); info!(self.logger, "Loaded component groups."); } From e56ded7d102e70beea0bd75e0778c88364992f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 16:31:13 +0200 Subject: [PATCH 016/140] WIP thread_local in searcher --- app/gui/src/controller/searcher.rs | 37 +++++++++++++++++++ .../controller/searcher/component/builder.rs | 4 ++ 2 files changed, 41 insertions(+) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index ec5114326b9b..2e787b57f3d2 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -49,6 +49,39 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; /// See also [`Searcher::add_enso_project_entries`]. const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; +thread_local! { + // TODO[MC]: can it be just slice? `[Rc]` + static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = vec![ + Rc::new(component::Virtual { + name: "text input", + code: "\"\"", + this_arg: None, + argument_types: vec![], + // FIXME[MC] + return_type: None, + imports: vec![], + // FIXME[MC] + documentation_html: Some("This will allow you to enter some text easily."), + method_id: None, + // FIXME[MC] possible to fix to use icon::Id? + icon: "TextInput".into(), + }), + Rc::new(component::Virtual { + name: "number input", + code: "0", + this_arg: None, + argument_types: vec![], + // FIXME[MC] + return_type: None, + imports: vec![], + // FIXME[MC] + documentation_html: Some("This will allow you to enter a number easily."), + method_id: None, + // FIXME[MC] possible to fix to use icon::Id? + icon: "NumberInput".into(), + }), + ]; +} // ============== // === Errors === @@ -1043,6 +1076,10 @@ impl Searcher { ) -> component::List { let mut builder = self.list_builder_with_favorites.deref().clone(); builder.extend_list_and_allow_favorites_with_ids(&self.database, entry_ids); + // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at comptime? + let base_lib = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); + builder.insert_virtual_components_in_favorites_group(base_lib, "Input", components); builder.build() } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index db3804df783e..476136776383 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -25,6 +25,7 @@ use crate::model::execution_context; use crate::model::suggestion_database; use double_representation::module; +use double_representation::project; @@ -163,6 +164,9 @@ impl List { .collect(); } + pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { + } + fn lookup_module_group( &mut self, db: &model::SuggestionDatabase, From 7d7875382a10e7780c8e283cb1d4bb89cb8c1377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 16:34:27 +0200 Subject: [PATCH 017/140] WIP find group by fully qual. name --- app/gui/src/controller/searcher/component/builder.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 476136776383..1aed30080653 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -165,6 +165,14 @@ impl List { } pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { + let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); + let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); + for group in favorites_groups.iter_mut() { + if group.library == library && group.name.as_ref() == group_name.as_ref() { + DEBUG!("MCDBG found library: " group.library " " group.name); + } + } + self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); } fn lookup_module_group( From 605107279bf429b606a55db40367a57f62557dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 16:48:55 +0200 Subject: [PATCH 018/140] WIP add library in comp::Group --- .../controller/searcher/component/builder.rs | 69 ++++++++++--------- .../controller/searcher/component/group.rs | 57 ++++++++------- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 1aed30080653..08fe4db59899 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -100,9 +100,10 @@ impl List { /// returned object, components passed to the method which have their parent module ID equal /// to `module_id` will be cloned into [`component::List::local_scope`]. pub fn with_local_scope_module_id(self, module_id: component::Id) -> Self { + use crate::controller::searcher::component::Group; const LOCAL_SCOPE_GROUP_NAME: &str = "Local Scope"; let id = Some(module_id); - let local_scope = component::Group::from_name_and_id(LOCAL_SCOPE_GROUP_NAME, id); + let local_scope = Group::from_library_name_and_id(None, LOCAL_SCOPE_GROUP_NAME, id); Self { local_scope, ..self } } @@ -168,8 +169,8 @@ impl List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); for group in favorites_groups.iter_mut() { - if group.library == library && group.name.as_ref() == group_name.as_ref() { - DEBUG!("MCDBG found library: " group.library " " group.name); + if group.library == Some(library) && group.name.as_str() == group_name.as_ref() { + DEBUG!("MCDBG found library: " group.library;? " " group.name); } } self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); @@ -235,37 +236,37 @@ impl List { // FIXME[MC]: do it explicitly from searcher through a separate method // TODO(LATER): how to make it possible to add virtual entries only to Standard.Base.Input // group, not to any group named `Input`? - { - let vgroup = component::Group::from_name_and_virtual_entries("Favs", [ - Rc::new(component::Virtual { - name: "text input", - code: "\"\"", - this_arg: None, - argument_types: vec![], - // FIXME[MC] - return_type: None, - imports: vec![], - documentation_html: Some("This will allow you to enter some text easily."), - method_id: None, - // FIXME[MC] possible to fix? - icon: "TextInput".into(), - }), - Rc::new(component::Virtual { - name: "number input", - code: "0", - this_arg: None, - argument_types: vec![], - // FIXME[MC] - return_type: None, - imports: vec![], - documentation_html: Some("This will allow you to enter a number easily."), - method_id: None, - // FIXME[MC] possible to fix? - icon: "NumberInput".into(), - }), - ]); - favorites_groups.insert(0, vgroup); - } + // { + // let vgroup = component::Group::from_name_and_virtual_entries("Favs", [ + // Rc::new(component::Virtual { + // name: "text input", + // code: "\"\"", + // this_arg: None, + // argument_types: vec![], + // // FIXME[MC] + // return_type: None, + // imports: vec![], + // documentation_html: Some("This will allow you to enter some text easily."), + // method_id: None, + // // FIXME[MC] possible to fix? + // icon: "TextInput".into(), + // }), + // Rc::new(component::Virtual { + // name: "number input", + // code: "0", + // this_arg: None, + // argument_types: vec![], + // // FIXME[MC] + // return_type: None, + // imports: vec![], + // documentation_html: Some("This will allow you to enter a number easily."), + // method_id: None, + // // FIXME[MC] possible to fix? + // icon: "NumberInput".into(), + // }), + // ]); + // favorites_groups.insert(0, vgroup); + // } for group in favorites_groups.iter_mut() { group.retain_entries(|e| match e.kind { component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 81b3bbe61844..507b4f7eb163 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -11,6 +11,7 @@ use crate::controller::searcher::component::NoSuchGroup; use crate::model::execution_context; use crate::model::suggestion_database; +use double_representation::project; use ensogl::data::color; use std::cmp; @@ -24,6 +25,7 @@ use std::cmp; #[allow(missing_docs)] #[derive(Clone, Debug, Default)] pub struct Data { + pub library: Option, pub name: ImString, pub color: Option, /// A component corresponding to this group, e.g. the module of whose content the group @@ -38,8 +40,9 @@ pub struct Data { } impl Data { - fn from_name_and_id(name: impl Into, component_id: Option) -> Self { + fn from_library_name_and_id(library: Option, name: impl Into, component_id: Option) -> Self { Data { + library, name: name.into(), color: None, component_id, @@ -77,11 +80,12 @@ impl Deref for Group { impl Group { /// Create a named empty group referring to module with specified component ID. - pub fn from_name_and_id( + pub fn from_library_name_and_id( + library: Option, name: impl Into, component_id: Option, ) -> Self { - Self { data: Rc::new(Data::from_name_and_id(name, component_id)) } + Self { data: Rc::new(Data::from_library_name_and_id(library, name, component_id)) } } /// Create empty group referring to some module component. @@ -93,30 +97,32 @@ impl Group { } else { entry.module.name().into() }; - Self::from_name_and_id(name, Some(component_id)) + let library = entry.module.project_name.clone(); + Self::from_library_name_and_id(Some(library), name, Some(component_id)) } - pub fn from_name_and_virtual_entries( - name: impl Into, - entries: impl IntoIterator>, - ) -> Self { - let components = entries - .into_iter() - .map(|suggestion| Component { - kind: component::Kind::Virtual { suggestion }, - match_info: default(), - }) - .collect_vec(); - let group_data = Data { - name: name.into(), - color: None, - component_id: None, - matched_items: Cell::new(components.len()), - initial_entries_order: components.clone(), - entries: RefCell::new(components), - }; - Group { data: Rc::new(group_data) } - } + // pub fn from_name_and_virtual_entries( + // name: impl Into, + // entries: impl IntoIterator>, + // ) -> Self { + // let components = entries + // .into_iter() + // .map(|suggestion| Component { + // kind: component::Kind::Virtual { suggestion }, + // match_info: default(), + // }) + // .collect_vec(); + // let group_data = Data { + // library: None, + // name: name.into(), + // color: None, + // component_id: None, + // matched_items: Cell::new(components.len()), + // initial_entries_order: components.clone(), + // entries: RefCell::new(components), + // }; + // Group { data: Rc::new(group_data) } + // } /// Construct from [`execution_context::ComponentGroup`] components looked up in the suggestion /// database by their full qualified name. Returns a group containing only the successfully @@ -135,6 +141,7 @@ impl Group { let any_components_found_in_db = !looked_up_components.is_empty(); any_components_found_in_db.then(|| { let group_data = Data { + library: Some(group.library.clone()), name: group.name.clone(), color: group.color, component_id: None, From 15383fb4635ca22f2e0857d4da8f7a0d40378f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 16:50:57 +0200 Subject: [PATCH 019/140] fix to compile --- app/gui/src/controller/searcher/component/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 08fe4db59899..7e4108742525 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -169,7 +169,7 @@ impl List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); for group in favorites_groups.iter_mut() { - if group.library == Some(library) && group.name.as_str() == group_name.as_ref() { + if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { DEBUG!("MCDBG found library: " group.library;? " " group.name); } } From d13dcbe086ac3fe1f664240522e82d4d208fd77a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 17:00:31 +0200 Subject: [PATCH 020/140] add a fixme to refactor --- app/gui/src/controller/searcher/component/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 7e4108742525..85a9a2f9c6b9 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -166,6 +166,7 @@ impl List { } pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { + // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); for group in favorites_groups.iter_mut() { From 9b928faa2d9398c3ec8a503df1873d08a2d07781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 17:00:43 +0200 Subject: [PATCH 021/140] DEBUG libs+names in insert_... --- app/gui/src/controller/searcher/component/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 85a9a2f9c6b9..b589e42b206f 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -170,6 +170,7 @@ impl List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); for group in favorites_groups.iter_mut() { + DEBUG!("MCDBG blub: " group.library;? " " group.name;?); if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { DEBUG!("MCDBG found library: " group.library;? " " group.name); } From f93ca4d59e78af7b43014a88fe02576561f15ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 17:14:35 +0200 Subject: [PATCH 022/140] move insert_... to initialization of builder --- app/gui/src/controller/searcher.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 2e787b57f3d2..d7dc01795a5a 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1076,10 +1076,6 @@ impl Searcher { ) -> component::List { let mut builder = self.list_builder_with_favorites.deref().clone(); builder.extend_list_and_allow_favorites_with_ids(&self.database, entry_ids); - // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at comptime? - let base_lib = project::QualifiedName::from_segments("Standard", "Base").unwrap(); - let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); - builder.insert_virtual_components_in_favorites_group(base_lib, "Input", components); builder.build() } @@ -1224,6 +1220,10 @@ fn component_list_builder_with_favorites<'a>( builder = builder.with_local_scope_module_id(id); } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); + // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at comptime? + let base_lib = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); + builder.insert_virtual_components_in_favorites_group(base_lib, "Input", components); builder } From 670d99f746db8f9b483c16bf677eabc0443b6cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 17:39:14 +0200 Subject: [PATCH 023/140] insert_entries --- app/gui/src/controller/searcher/component/builder.rs | 6 ++++++ app/gui/src/controller/searcher/component/group.rs | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index b589e42b206f..bc859201eafe 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -166,12 +166,18 @@ impl List { } pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { + let virtual_components = components.into_iter().map(|c| Component { + kind: component::Kind::Virtual { suggestion: c }, + match_info: default(), + }).collect_vec(); // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); + let mut inserted = false; for group in favorites_groups.iter_mut() { DEBUG!("MCDBG blub: " group.library;? " " group.name;?); if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { + group.insert_entries(&virtual_components); DEBUG!("MCDBG found library: " group.library;? " " group.name); } } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 507b4f7eb163..6df56fc56395 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -153,6 +153,13 @@ impl Group { }) } + pub fn insert_entries(&mut self, entries: &[Component]) { + let group_data = Rc::make_mut(&mut self.data); + group_data.entries.borrow_mut().splice(0..0, entries.iter().cloned()); + group_data.initial_entries_order.splice(0..0, entries.iter().cloned()); + group_data.update_matched_items(); + } + /// Modify the group keeping only the [`Component`]s for which `f` returns [`true`]. pub fn retain_entries(&mut self, mut f: F) where F: FnMut(&Component) -> bool { From ccf61f30ada823f795547f122fa7e95017a981bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 28 Jul 2022 17:39:27 +0200 Subject: [PATCH 024/140] WIP if !inserted ... --- app/gui/src/controller/searcher/component/builder.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index bc859201eafe..28afb6acaca2 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -179,8 +179,13 @@ impl List { if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { group.insert_entries(&virtual_components); DEBUG!("MCDBG found library: " group.library;? " " group.name); + inserted = true; } } + if !inserted { + // FIXME[mc] + DEBUG!("FIXME insert new group with virtual entries at the beginning"); + } self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); } From 903490ffb213e9bc08eb5c1c9b3a92f09434919c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 10:44:56 +0200 Subject: [PATCH 025/140] WIP --- .../controller/searcher/component/builder.rs | 37 ++++++++++----- .../controller/searcher/component/group.rs | 45 ++++++++++--------- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 28afb6acaca2..df471182ede8 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -173,19 +173,34 @@ impl List { // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); - let mut inserted = false; - for group in favorites_groups.iter_mut() { - DEBUG!("MCDBG blub: " group.library;? " " group.name;?); - if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { - group.insert_entries(&virtual_components); - DEBUG!("MCDBG found library: " group.library;? " " group.name); - inserted = true; - } - } - if !inserted { - // FIXME[mc] + + let group_with_matching_name = favorites_groups.iter_mut().find(|g| + g.library.as_ref() == Some(&library) && g.name.as_str() == group_name.as_ref()); + if let Some(group) = group_with_matching_name { + // FIXME: insert entries to group + group.insert_entries(&virtual_components); + DEBUG!("MCDBG found library: " group.library;? " " group.name); + } else { + // FIXME: create new group and insert it at beginning + let new_group = component::Group::from_name_and_virtual_entries(Some(library), group_name.as_str(), components); + favorites_groups.insert(0, new_group); DEBUG!("FIXME insert new group with virtual entries at the beginning"); } + + // let mut inserted = false; + // for group in favorites_groups.iter_mut() { + // DEBUG!("MCDBG blub: " group.library;? " " group.name;?); + // if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { + // group.insert_entries(&virtual_components); + // DEBUG!("MCDBG found library: " group.library;? " " group.name); + // inserted = true; + // } + // } + // if !inserted { + // let new_group = component::Group::from_name_and_virtual_entries(Some(library), group_name.as_str(), components); + // // FIXME[mc] + // DEBUG!("FIXME insert new group with virtual entries at the beginning"); + // } self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 6df56fc56395..3dcfb1902594 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -101,28 +101,29 @@ impl Group { Self::from_library_name_and_id(Some(library), name, Some(component_id)) } - // pub fn from_name_and_virtual_entries( - // name: impl Into, - // entries: impl IntoIterator>, - // ) -> Self { - // let components = entries - // .into_iter() - // .map(|suggestion| Component { - // kind: component::Kind::Virtual { suggestion }, - // match_info: default(), - // }) - // .collect_vec(); - // let group_data = Data { - // library: None, - // name: name.into(), - // color: None, - // component_id: None, - // matched_items: Cell::new(components.len()), - // initial_entries_order: components.clone(), - // entries: RefCell::new(components), - // }; - // Group { data: Rc::new(group_data) } - // } + pub fn from_name_and_virtual_components( + library: Option, + group_name: impl Into, + entries: impl IntoIterator>, + ) -> Self { + let components = entries + .into_iter() + .map(|suggestion| Component { + kind: component::Kind::Virtual { suggestion }, + match_info: default(), + }) + .collect_vec(); + let group_data = Data { + library, + name: group_name.into(), + color: None, + component_id: None, + matched_items: Cell::new(components.len()), + initial_entries_order: components.clone(), + entries: RefCell::new(components), + }; + Group { data: Rc::new(group_data) } + } /// Construct from [`execution_context::ComponentGroup`] components looked up in the suggestion /// database by their full qualified name. Returns a group containing only the successfully From 05425d664a4ef053aabc7bf892ee8eb20992ef2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 10:48:16 +0200 Subject: [PATCH 026/140] fix to compile --- .../src/controller/searcher/component/builder.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index df471182ede8..73141a89e0de 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -166,10 +166,6 @@ impl List { } pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { - let virtual_components = components.into_iter().map(|c| Component { - kind: component::Kind::Virtual { suggestion: c }, - match_info: default(), - }).collect_vec(); // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); @@ -177,12 +173,15 @@ impl List { let group_with_matching_name = favorites_groups.iter_mut().find(|g| g.library.as_ref() == Some(&library) && g.name.as_str() == group_name.as_ref()); if let Some(group) = group_with_matching_name { - // FIXME: insert entries to group + // FIXME: code duplicated with c::Group::from_name_and_virtual_components() + let virtual_components = components.into_iter().map(|c| Component { + kind: component::Kind::Virtual { suggestion: c }, + match_info: default(), + }).collect_vec(); group.insert_entries(&virtual_components); DEBUG!("MCDBG found library: " group.library;? " " group.name); } else { - // FIXME: create new group and insert it at beginning - let new_group = component::Group::from_name_and_virtual_entries(Some(library), group_name.as_str(), components); + let new_group = component::Group::from_name_and_virtual_components(Some(library), group_name.as_ref(), components); favorites_groups.insert(0, new_group); DEBUG!("FIXME insert new group with virtual entries at the beginning"); } From 36740667271c786971484d6c02734409c37dcc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 12:50:10 +0200 Subject: [PATCH 027/140] CLEANUP one comment --- .../controller/searcher/component/builder.rs | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 73141a89e0de..8e6c73f9df82 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -260,40 +260,6 @@ impl List { fn build_favorites_and_add_to_all_components(&mut self) -> component::group::List { let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); - // FIXME[MC]: do it explicitly from searcher through a separate method - // TODO(LATER): how to make it possible to add virtual entries only to Standard.Base.Input - // group, not to any group named `Input`? - // { - // let vgroup = component::Group::from_name_and_virtual_entries("Favs", [ - // Rc::new(component::Virtual { - // name: "text input", - // code: "\"\"", - // this_arg: None, - // argument_types: vec![], - // // FIXME[MC] - // return_type: None, - // imports: vec![], - // documentation_html: Some("This will allow you to enter some text easily."), - // method_id: None, - // // FIXME[MC] possible to fix? - // icon: "TextInput".into(), - // }), - // Rc::new(component::Virtual { - // name: "number input", - // code: "0", - // this_arg: None, - // argument_types: vec![], - // // FIXME[MC] - // return_type: None, - // imports: vec![], - // documentation_html: Some("This will allow you to enter a number easily."), - // method_id: None, - // // FIXME[MC] possible to fix? - // icon: "NumberInput".into(), - // }), - // ]); - // favorites_groups.insert(0, vgroup); - // } for group in favorites_groups.iter_mut() { group.retain_entries(|e| match e.kind { component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), From 2504aacd2b1474047f9f92c642a75d892565e245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 12:50:19 +0200 Subject: [PATCH 028/140] WIP group::QualifiedName --- .../controller/searcher/component/builder.rs | 10 ++--- .../controller/searcher/component/group.rs | 43 +++++++++++++------ app/gui/src/model/execution_context.rs | 12 +++--- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 8e6c73f9df82..342e384312fa 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -103,7 +103,7 @@ impl List { use crate::controller::searcher::component::Group; const LOCAL_SCOPE_GROUP_NAME: &str = "Local Scope"; let id = Some(module_id); - let local_scope = Group::from_library_name_and_id(None, LOCAL_SCOPE_GROUP_NAME, id); + let local_scope = Group::from_name_project_and_id(LOCAL_SCOPE_GROUP_NAME, None, id); Self { local_scope, ..self } } @@ -165,13 +165,13 @@ impl List { .collect(); } - pub fn insert_virtual_components_in_favorites_group(&mut self, library: project::QualifiedName, group_name: impl AsRef, components: impl IntoIterator>) { + pub fn insert_virtual_components_in_favorites_group(&mut self, name: component::group::QualifiedName, components: impl IntoIterator>) { // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); let group_with_matching_name = favorites_groups.iter_mut().find(|g| - g.library.as_ref() == Some(&library) && g.name.as_str() == group_name.as_ref()); + g.qualified_name().as_ref() == Some(&name)); if let Some(group) = group_with_matching_name { // FIXME: code duplicated with c::Group::from_name_and_virtual_components() let virtual_components = components.into_iter().map(|c| Component { @@ -179,9 +179,9 @@ impl List { match_info: default(), }).collect_vec(); group.insert_entries(&virtual_components); - DEBUG!("MCDBG found library: " group.library;? " " group.name); + DEBUG!("MCDBG found library: " group.project;? " " group.name); } else { - let new_group = component::Group::from_name_and_virtual_components(Some(library), group_name.as_ref(), components); + let new_group = component::Group::from_qualified_name_and_virtual_components(name, components); favorites_groups.insert(0, new_group); DEBUG!("FIXME insert new group with virtual entries at the beginning"); } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 3dcfb1902594..4ec8bd5d0e1a 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -17,6 +17,18 @@ use std::cmp; +// ===================== +// === QualifiedName === +// ===================== + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct QualifiedName { + pub project: project::QualifiedName, + pub name: ImString, +} + + + // ============ // === Data === // ============ @@ -25,7 +37,7 @@ use std::cmp; #[allow(missing_docs)] #[derive(Clone, Debug, Default)] pub struct Data { - pub library: Option, + pub project: Option, pub name: ImString, pub color: Option, /// A component corresponding to this group, e.g. the module of whose content the group @@ -40,9 +52,9 @@ pub struct Data { } impl Data { - fn from_library_name_and_id(library: Option, name: impl Into, component_id: Option) -> Self { + fn from_name_project_and_id(name: impl Into, project: Option, component_id: Option) -> Self { Data { - library, + project, name: name.into(), color: None, component_id, @@ -80,12 +92,12 @@ impl Deref for Group { impl Group { /// Create a named empty group referring to module with specified component ID. - pub fn from_library_name_and_id( - library: Option, + pub fn from_name_project_and_id( name: impl Into, + project: Option, component_id: Option, ) -> Self { - Self { data: Rc::new(Data::from_library_name_and_id(library, name, component_id)) } + Self { data: Rc::new(Data::from_name_project_and_id(name, project, component_id)) } } /// Create empty group referring to some module component. @@ -97,13 +109,12 @@ impl Group { } else { entry.module.name().into() }; - let library = entry.module.project_name.clone(); - Self::from_library_name_and_id(Some(library), name, Some(component_id)) + let project_name = entry.module.project_name.clone(); + Self::from_name_project_and_id(name, Some(project_name), Some(component_id)) } - pub fn from_name_and_virtual_components( - library: Option, - group_name: impl Into, + pub fn from_qualified_name_and_virtual_components( + qualified_name: QualifiedName, entries: impl IntoIterator>, ) -> Self { let components = entries @@ -114,8 +125,8 @@ impl Group { }) .collect_vec(); let group_data = Data { - library, - name: group_name.into(), + project: Some(qualified_name.project), + name: qualified_name.name, color: None, component_id: None, matched_items: Cell::new(components.len()), @@ -142,7 +153,7 @@ impl Group { let any_components_found_in_db = !looked_up_components.is_empty(); any_components_found_in_db.then(|| { let group_data = Data { - library: Some(group.library.clone()), + project: Some(group.project.clone()), name: group.name.clone(), color: group.color, component_id: None, @@ -221,6 +232,10 @@ impl Group { } } + pub fn qualified_name(&self) -> Option { + self.project.map(|p| QualifiedName { project: p.clone(), name: self.name.clone() }) + } + /// Get the number of entries. pub fn len(&self) -> usize { self.entries.borrow().len() diff --git a/app/gui/src/model/execution_context.rs b/app/gui/src/model/execution_context.rs index f5a9aaa5e742..cb4aa2d89e72 100644 --- a/app/gui/src/model/execution_context.rs +++ b/app/gui/src/model/execution_context.rs @@ -288,10 +288,10 @@ pub struct AttachedVisualization { #[allow(missing_docs)] #[derive(Clone, Debug, PartialEq)] pub struct ComponentGroup { - /// The fully qualified library name. - pub library: project::QualifiedName, - /// The group name without the library name prefix. E.g. given the `Standard.Base.Group 1` - /// group reference, the `name` field contains `Group 1`. + /// The fully qualified name of the library project. + pub project: project::QualifiedName, + /// The group name without the library project name prefix. E.g. given the `Standard.Base.Group + /// 1` group reference, the `name` field contains `Group 1`. pub name: ImString, /// An optional color to use when displaying the component group. pub color: Option, @@ -303,11 +303,11 @@ impl ComponentGroup { pub fn from_language_server_protocol_struct( group: language_server::LibraryComponentGroup, ) -> FallibleResult { - let library = group.library.try_into()?; + let project = group.library.try_into()?; let name = group.name.into(); let color = group.color.as_ref().and_then(|c| color::Rgb::from_css_hex(c)); let components = group.exports.into_iter().map(|e| e.name.into()).collect(); - Ok(ComponentGroup { library, name, color, components }) + Ok(ComponentGroup { project, name, color, components }) } } From b65f8adaa9b6e0f6bb3bb20eda89b2fd8412d8dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 14:42:16 +0200 Subject: [PATCH 029/140] fix to compile --- app/gui/src/controller/searcher.rs | 5 +++-- app/gui/src/controller/searcher/component/group.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index d7dc01795a5a..3b62462afdbc 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1221,9 +1221,10 @@ fn component_list_builder_with_favorites<'a>( } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at comptime? - let base_lib = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let group_name = component::group::QualifiedName { project, name: "Input".into() }; let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); - builder.insert_virtual_components_in_favorites_group(base_lib, "Input", components); + builder.insert_virtual_components_in_favorites_group(group_name, components); builder } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 4ec8bd5d0e1a..3ae75bf871c6 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -233,7 +233,7 @@ impl Group { } pub fn qualified_name(&self) -> Option { - self.project.map(|p| QualifiedName { project: p.clone(), name: self.name.clone() }) + self.project.as_ref().map(|p| QualifiedName { project: p.clone(), name: self.name.clone() }) } /// Get the number of entries. From 07ff1e19bb2f1448db90c44e258542231f52416b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 14:49:29 +0200 Subject: [PATCH 030/140] rename fn --- app/gui/src/controller/searcher/component/builder.rs | 2 +- app/gui/src/controller/searcher/component/group.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 342e384312fa..15663fc79513 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -103,7 +103,7 @@ impl List { use crate::controller::searcher::component::Group; const LOCAL_SCOPE_GROUP_NAME: &str = "Local Scope"; let id = Some(module_id); - let local_scope = Group::from_name_project_and_id(LOCAL_SCOPE_GROUP_NAME, None, id); + let local_scope = Group::from_name_and_project_and_id(LOCAL_SCOPE_GROUP_NAME, None, id); Self { local_scope, ..self } } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 3ae75bf871c6..1d816f91d004 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -52,7 +52,7 @@ pub struct Data { } impl Data { - fn from_name_project_and_id(name: impl Into, project: Option, component_id: Option) -> Self { + fn from_name_and_project_and_id(name: impl Into, project: Option, component_id: Option) -> Self { Data { project, name: name.into(), @@ -92,12 +92,12 @@ impl Deref for Group { impl Group { /// Create a named empty group referring to module with specified component ID. - pub fn from_name_project_and_id( + pub fn from_name_and_project_and_id( name: impl Into, project: Option, component_id: Option, ) -> Self { - Self { data: Rc::new(Data::from_name_project_and_id(name, project, component_id)) } + Self { data: Rc::new(Data::from_name_and_project_and_id(name, project, component_id)) } } /// Create empty group referring to some module component. @@ -110,7 +110,7 @@ impl Group { entry.module.name().into() }; let project_name = entry.module.project_name.clone(); - Self::from_name_project_and_id(name, Some(project_name), Some(component_id)) + Self::from_name_and_project_and_id(name, Some(project_name), Some(component_id)) } pub fn from_qualified_name_and_virtual_components( From 1d254def9a86b0043e11dd069da4e7ab9d86fc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 16:08:35 +0200 Subject: [PATCH 031/140] WIP fixing tests --- app/gui/src/controller/searcher/component.rs | 10 +++++++++- app/gui/src/controller/searcher/component/builder.rs | 10 +++++----- app/gui/src/model/execution_context/plain.rs | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 4f586159bf09..06ae62027082 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -127,6 +127,13 @@ impl Component { self.to_string() } + pub fn id(&self) -> Option { + match self.kind { + Kind::FromDb { id, .. } => Some(*id), + Kind::Virtual { .. } => None, + } + } + /// Checks if component is filtered out. pub fn is_filtered_out(&self) -> bool { matches!(*self.match_info.borrow(), MatchInfo::DoesNotMatch) @@ -384,6 +391,7 @@ pub(crate) mod tests { ) -> Vec { let db_entries = component_ids.iter().map(|id| db.lookup(*id).unwrap()); let group = crate::model::execution_context::ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Test Group 1".into(), color: None, components: db_entries.into_iter().map(|e| e.qualified_name()).collect(), @@ -403,7 +411,7 @@ pub(crate) mod tests { .borrow() .iter() .take_while(|c| matches!(*c.match_info.borrow(), MatchInfo::Matches { .. })) - .map(|c| *c.id) + .filter_map(|c| c.id()) .collect_vec(); assert_eq!(ids_of_matches, expected_ids); } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 15663fc79513..a9d80bf0eede 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -292,11 +292,11 @@ mod tests { } impl<'a> From<&'a component::Group> for ComparableGroupData<'a> { - fn from(component: &'a component::Group) -> Self { + fn from(group: &'a component::Group) -> Self { Self { - name: component.name.as_str(), - component_id: component.component_id, - entries: component.entries.borrow().iter().map(|e| *e.id).collect(), + name: group.name.as_str(), + component_id: group.component_id, + entries: group.entries.borrow().iter().filter_map(|e| e.id()).collect(), } } } @@ -399,7 +399,7 @@ mod tests { assert_eq!(module_subgroups, expected); let local_scope_entries = &list.local_scope.entries; - let local_scope_ids = local_scope_entries.borrow().iter().map(|e| *e.id).collect_vec(); + let local_scope_ids = local_scope_entries.borrow().iter().filter_map(|e| e.id()).collect_vec(); let expected_ids = vec![5, 6]; assert_eq!(local_scope_ids, expected_ids); } diff --git a/app/gui/src/model/execution_context/plain.rs b/app/gui/src/model/execution_context/plain.rs index d92e14804a78..27024835c179 100644 --- a/app/gui/src/model/execution_context/plain.rs +++ b/app/gui/src/model/execution_context/plain.rs @@ -313,7 +313,8 @@ pub mod test { } fn component_groups(&self) -> RefCell>> { - let groups = self.component_groups.iter().map(|g| g.clone().into()).collect(); + let group_from_library_group = |g: LibraryComponentGroup| g.clone().try_into().unwrap(); + let groups = self.component_groups.iter().map(group_from_library_group).collect(); RefCell::new(Rc::new(groups)) } From de90f8cafb64efce03be40cdd029043855861734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 16:19:14 +0200 Subject: [PATCH 032/140] WIP fixing tests --- app/gui/src/controller/searcher/component/builder.rs | 2 ++ app/gui/src/controller/searcher/component/group.rs | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index a9d80bf0eede..9009ee14b7e5 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -418,6 +418,7 @@ mod tests { assert_eq!(db.lookup_by_qualified_name_str(QN_NOT_IN_DB), None); let groups = [ execution_context::ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Group 1".into(), color: None, components: vec![ @@ -431,6 +432,7 @@ mod tests { ], }, execution_context::ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Group 2".into(), color: None, components: vec![ diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 1d816f91d004..ef902993f5a0 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -373,6 +373,7 @@ mod tests { // order. Some of the names correspond to entries present in the suggestion database, // some do not. let ec_group = execution_context::ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Test Group 1".into(), color: color::Rgb::from_css_hex("#aabbcc"), components: vec![ @@ -394,15 +395,14 @@ mod tests { assert_eq!((color.red * 255.0) as u8, 0xaa); assert_eq!((color.green * 255.0) as u8, 0xbb); assert_eq!((color.blue * 255.0) as u8, 0xcc); - let entry_ids_and_names = group + let entry_ids = group .entries .borrow() .iter() - .map(|e| (*e.id, e.suggestion.name.to_string())) + .map(|e| e.id().unwrap()) .collect_vec(); - let expected_ids_and_names = - vec![(6, "fun2".to_string()), (10, "fun6".to_string()), (5, "fun1".to_string())]; - assert_eq!(entry_ids_and_names, expected_ids_and_names); + let expected_ids = vec![6, 10, 5]; + assert_eq!(entry_ids, expected_ids); } // Test constructing a component group from an [`execution_context::ComponentGroup`] containing From 6b0dcfceb9b31ed2cd5272fd12ccdacbcd549348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 16:25:17 +0200 Subject: [PATCH 033/140] WIP fixing tests --- app/gui/src/controller/searcher/component.rs | 5 +++-- app/gui/src/controller/searcher/component/group.rs | 1 + app/gui/src/model/execution_context/plain.rs | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 06ae62027082..e2df3c88033a 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -321,6 +321,7 @@ pub(crate) mod tests { use crate::model::suggestion_database::entry::Kind; use double_representation::module; + use double_representation::project; use engine_protocol::language_server; @@ -488,7 +489,7 @@ pub(crate) mod tests { // ("test.Test.TopModule1.SubModule2"). let content = list.get_module_content(3).unwrap(); let expected_content_ids = vec![9, 4]; - let content_ids = content.entries.borrow().iter().map(|entry| *entry.id).collect_vec(); + let content_ids = content.entries.borrow().iter().map(|e| e.id().unwrap()).collect_vec(); assert_eq!(content_ids, expected_content_ids); let direct_submodules = list.submodules_of(3).unwrap(); let expected_direct_submodules_ids = vec![Some(4)]; @@ -499,7 +500,7 @@ pub(crate) mod tests { // ("test.Test.TopModule1.SubModule1.SubSubModule"). let content = list.get_module_content(4).unwrap(); let expected_content_ids = vec![10]; - let content_ids = content.entries.borrow().iter().map(|entry| *entry.id).collect_vec(); + let content_ids = content.entries.borrow().iter().map(|e| e.id().unwrap()).collect_vec(); assert_eq!(content_ids, expected_content_ids); } } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index ef902993f5a0..77589a2607e1 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -412,6 +412,7 @@ mod tests { let logger = Logger::new("tests::constructing_component_group_from_names_not_found_in_db"); let suggestion_db = Rc::new(mock_suggestion_db(logger)); let ec_group = execution_context::ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Input".into(), color: None, components: vec!["NAME.NOT.FOUND.IN.DB".into()], diff --git a/app/gui/src/model/execution_context/plain.rs b/app/gui/src/model/execution_context/plain.rs index 27024835c179..a51e16cb693a 100644 --- a/app/gui/src/model/execution_context/plain.rs +++ b/app/gui/src/model/execution_context/plain.rs @@ -313,8 +313,9 @@ pub mod test { } fn component_groups(&self) -> RefCell>> { - let group_from_library_group = |g: LibraryComponentGroup| g.clone().try_into().unwrap(); - let groups = self.component_groups.iter().map(group_from_library_group).collect(); + use engine_protocol::language_server::LibraryComponentGroup; + let group_from_lib_group = |g: &LibraryComponentGroup| g.clone().try_into().unwrap(); + let groups = self.component_groups.iter().map(group_from_lib_group).collect(); RefCell::new(Rc::new(groups)) } From a23234bad4845be5c5aa33544602b52a3aa3dd5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 16:36:23 +0200 Subject: [PATCH 034/140] fix tests to compile\ --- app/gui/src/controller/searcher.rs | 8 ++++++-- app/gui/src/model/execution_context/synchronized.rs | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 3b62462afdbc..b36bd829103d 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1854,7 +1854,11 @@ pub mod test { format!("{}.{}", entry1.module.project_name.project, entry1.module.name()); assert_eq!(module_group.name, expected_group_name); let entries = module_group.entries.borrow(); - assert_matches!(entries.as_slice(), [e1, e2] if e1.suggestion.name == entry1.name && e2.suggestion.name == entry9.name); + let entry_name = |e: &component::Component| match &e.kind { + component::Kind::FromDb { suggestion, .. } => suggestion.name.clone(), + component::Kind::Virtual { suggestion } => suggestion.name.into(), + }; + assert_matches!(entries.as_slice(), [e1, e2] if entry_name(e1) == entry1.name && entry_name(e2) == entry9.name); } else { ipanic!("Wrong top modules in Component List: {components.top_modules():?}"); } @@ -1864,7 +1868,7 @@ pub mod test { assert_eq!(favorites_group.name, "Test Group 1"); let favorites_entries = favorites_group.entries.borrow(); assert_eq!(favorites_entries.len(), 1); - assert_eq!(*favorites_entries[0].id, 1); + assert_eq!(favorites_entries[0].id().unwrap(), 1); } #[wasm_bindgen_test] diff --git a/app/gui/src/model/execution_context/synchronized.rs b/app/gui/src/model/execution_context/synchronized.rs index 09474c7ffe46..d96eb0454b21 100644 --- a/app/gui/src/model/execution_context/synchronized.rs +++ b/app/gui/src/model/execution_context/synchronized.rs @@ -327,6 +327,7 @@ pub mod test { use crate::model::module::QualifiedName; use crate::model::traits::*; + use double_representation::project; use engine_protocol::language_server::response; use engine_protocol::language_server::CapabilityRegistration; use engine_protocol::language_server::ExpressionUpdates; @@ -623,6 +624,7 @@ pub mod test { // Verify that the second component group was parsed and has expected contents. assert_eq!(groups[1], ComponentGroup { + project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), name: "Input".into(), color: None, components: vec!["Standard.Base.System.File.new".into(),], From c059e587b0a3de567d71ae11fe3453d3525c9e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 1 Aug 2022 16:44:56 +0200 Subject: [PATCH 035/140] filter_map -> map(unwrap) in tests --- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/controller/searcher/component/builder.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index e2df3c88033a..8ba0211a2772 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -412,7 +412,7 @@ pub(crate) mod tests { .borrow() .iter() .take_while(|c| matches!(*c.match_info.borrow(), MatchInfo::Matches { .. })) - .filter_map(|c| c.id()) + .map(|c| c.id().unwrap()) .collect_vec(); assert_eq!(ids_of_matches, expected_ids); } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 9009ee14b7e5..3804e9cbf605 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -296,7 +296,7 @@ mod tests { Self { name: group.name.as_str(), component_id: group.component_id, - entries: group.entries.borrow().iter().filter_map(|e| e.id()).collect(), + entries: group.entries.borrow().iter().map(|e| e.id().unwrap()).collect(), } } } @@ -399,7 +399,8 @@ mod tests { assert_eq!(module_subgroups, expected); let local_scope_entries = &list.local_scope.entries; - let local_scope_ids = local_scope_entries.borrow().iter().filter_map(|e| e.id()).collect_vec(); + let component_id = |c: &Component| c.id().unwrap(); + let local_scope_ids = local_scope_entries.borrow().iter().map(component_id).collect_vec(); let expected_ids = vec![5, 6]; assert_eq!(local_scope_ids, expected_ids); } From 6699a011ba875ad9a29fc595170fb4c72af8b4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 11:51:56 +0200 Subject: [PATCH 036/140] impl From> for Component --- app/gui/src/controller/searcher/component.rs | 9 +++++++++ app/gui/src/controller/searcher/component/builder.rs | 6 +----- app/gui/src/controller/searcher/component/group.rs | 5 +---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8ba0211a2772..8cc69a7c74ce 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -168,6 +168,15 @@ impl Component { } } +impl From> for Component { + fn from(suggestion: Rc) -> Self { + Self { + kind: Kind::Virtual { suggestion }, + match_info: default(), + } + } +} + impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.kind { diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 3804e9cbf605..e46696624751 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -173,11 +173,7 @@ impl List { let group_with_matching_name = favorites_groups.iter_mut().find(|g| g.qualified_name().as_ref() == Some(&name)); if let Some(group) = group_with_matching_name { - // FIXME: code duplicated with c::Group::from_name_and_virtual_components() - let virtual_components = components.into_iter().map(|c| Component { - kind: component::Kind::Virtual { suggestion: c }, - match_info: default(), - }).collect_vec(); + let virtual_components = components.into_iter().map(Into::into).collect_vec(); group.insert_entries(&virtual_components); DEBUG!("MCDBG found library: " group.project;? " " group.name); } else { diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 77589a2607e1..5c46e32b3405 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -119,10 +119,7 @@ impl Group { ) -> Self { let components = entries .into_iter() - .map(|suggestion| Component { - kind: component::Kind::Virtual { suggestion }, - match_info: default(), - }) + .map(Into::into) .collect_vec(); let group_data = Data { project: Some(qualified_name.project), From d452d4ebeb1510910e9f5805d64fe4e9c3595ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 11:52:05 +0200 Subject: [PATCH 037/140] CLEANUP some fragments --- .../controller/searcher/component/builder.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index e46696624751..b112b9d23160 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -169,33 +169,15 @@ impl List { // FIXME: factor out common part of this and build_favorites_... let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); - let group_with_matching_name = favorites_groups.iter_mut().find(|g| g.qualified_name().as_ref() == Some(&name)); if let Some(group) = group_with_matching_name { let virtual_components = components.into_iter().map(Into::into).collect_vec(); group.insert_entries(&virtual_components); - DEBUG!("MCDBG found library: " group.project;? " " group.name); } else { let new_group = component::Group::from_qualified_name_and_virtual_components(name, components); favorites_groups.insert(0, new_group); - DEBUG!("FIXME insert new group with virtual entries at the beginning"); } - - // let mut inserted = false; - // for group in favorites_groups.iter_mut() { - // DEBUG!("MCDBG blub: " group.library;? " " group.name;?); - // if group.library.as_ref() == Some(&library) && group.name.as_str() == group_name.as_ref() { - // group.insert_entries(&virtual_components); - // DEBUG!("MCDBG found library: " group.library;? " " group.name); - // inserted = true; - // } - // } - // if !inserted { - // let new_group = component::Group::from_name_and_virtual_entries(Some(library), group_name.as_str(), components); - // // FIXME[mc] - // DEBUG!("FIXME insert new group with virtual entries at the beginning"); - // } self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); } From ecb08b4c82cb18d63369606412a4477381b2bab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 12:07:07 +0200 Subject: [PATCH 038/140] take_grouping_and_order... + some tweaks --- .../controller/searcher/component/builder.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index b112b9d23160..82150108308c 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -165,20 +165,22 @@ impl List { .collect(); } - pub fn insert_virtual_components_in_favorites_group(&mut self, name: component::group::QualifiedName, components: impl IntoIterator>) { - // FIXME: factor out common part of this and build_favorites_... - let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); - let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); - let group_with_matching_name = favorites_groups.iter_mut().find(|g| - g.qualified_name().as_ref() == Some(&name)); + fn take_grouping_and_order_of_favorites_as_vec(&mut self) -> Vec { + std::mem::take(&mut self.grouping_and_order_of_favorites).into_iter().collect_vec() + } + + pub fn insert_virtual_components_in_favorites_group(&mut self, group_name: component::group::QualifiedName, virtual_components: impl IntoIterator>) { + use component::Group; + let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); + let group_with_matching_name = favorites_grouping.iter_mut().find(|g| + g.qualified_name().as_ref() == Some(&group_name)); if let Some(group) = group_with_matching_name { - let virtual_components = components.into_iter().map(Into::into).collect_vec(); - group.insert_entries(&virtual_components); + group.insert_entries(&virtual_components.into_iter().map(Into::into).collect_vec()); } else { - let new_group = component::Group::from_qualified_name_and_virtual_components(name, components); - favorites_groups.insert(0, new_group); + let group = Group::from_qualified_name_and_virtual_components(group_name, virtual_components); + favorites_grouping.insert(0, group); } - self.grouping_and_order_of_favorites = component::group::List::new(favorites_groups); + self.grouping_and_order_of_favorites = component::group::List::new(favorites_grouping); } fn lookup_module_group( @@ -236,8 +238,7 @@ impl List { } fn build_favorites_and_add_to_all_components(&mut self) -> component::group::List { - let grouping_and_order = std::mem::take(&mut self.grouping_and_order_of_favorites); - let mut favorites_groups = grouping_and_order.into_iter().collect_vec(); + let mut favorites_groups = self.take_grouping_and_order_of_favorites_as_vec(); for group in favorites_groups.iter_mut() { group.retain_entries(|e| match e.kind { component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), From ccc4f2d4b48eab5a5980643ba2dc728cd801629b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 12:09:42 +0200 Subject: [PATCH 039/140] cargo fmt + tweak --- app/gui/src/controller/searcher.rs | 3 ++- app/gui/src/controller/searcher/component.rs | 5 +--- .../controller/searcher/component/builder.rs | 14 ++++++++--- .../controller/searcher/component/group.rs | 25 ++++++++----------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index b36bd829103d..ef13c838c4bb 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1220,7 +1220,8 @@ fn component_list_builder_with_favorites<'a>( builder = builder.with_local_scope_module_id(id); } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); - // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at comptime? + // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at + // comptime? let project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); let group_name = component::group::QualifiedName { project, name: "Input".into() }; let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8cc69a7c74ce..66d68c5d42a5 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -170,10 +170,7 @@ impl Component { impl From> for Component { fn from(suggestion: Rc) -> Self { - Self { - kind: Kind::Virtual { suggestion }, - match_info: default(), - } + Self { kind: Kind::Virtual { suggestion }, match_info: default() } } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 82150108308c..69f95dfc7ec7 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -169,15 +169,21 @@ impl List { std::mem::take(&mut self.grouping_and_order_of_favorites).into_iter().collect_vec() } - pub fn insert_virtual_components_in_favorites_group(&mut self, group_name: component::group::QualifiedName, virtual_components: impl IntoIterator>) { + pub fn insert_virtual_components_in_favorites_group( + &mut self, + group_name: component::group::QualifiedName, + virtual_components: impl IntoIterator>, + ) { use component::Group; let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); - let group_with_matching_name = favorites_grouping.iter_mut().find(|g| - g.qualified_name().as_ref() == Some(&group_name)); + let group_with_matching_name = favorites_grouping + .iter_mut() + .find(|g| g.qualified_name().as_ref() == Some(&group_name)); if let Some(group) = group_with_matching_name { group.insert_entries(&virtual_components.into_iter().map(Into::into).collect_vec()); } else { - let group = Group::from_qualified_name_and_virtual_components(group_name, virtual_components); + let group = + Group::from_qualified_name_and_virtual_components(group_name, virtual_components); favorites_grouping.insert(0, group); } self.grouping_and_order_of_favorites = component::group::List::new(favorites_grouping); diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 5c46e32b3405..b872985056ea 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -24,7 +24,7 @@ use std::cmp; #[derive(Clone, Debug, PartialEq, Eq)] pub struct QualifiedName { pub project: project::QualifiedName, - pub name: ImString, + pub name: ImString, } @@ -52,7 +52,11 @@ pub struct Data { } impl Data { - fn from_name_and_project_and_id(name: impl Into, project: Option, component_id: Option) -> Self { + fn from_name_and_project_and_id( + name: impl Into, + project: Option, + component_id: Option, + ) -> Self { Data { project, name: name.into(), @@ -117,12 +121,9 @@ impl Group { qualified_name: QualifiedName, entries: impl IntoIterator>, ) -> Self { - let components = entries - .into_iter() - .map(Into::into) - .collect_vec(); + let components = entries.into_iter().map(Into::into).collect_vec(); let group_data = Data { - project: Some(qualified_name.project), + project: Some(qualified_name.project), name: qualified_name.name, color: None, component_id: None, @@ -230,7 +231,8 @@ impl Group { } pub fn qualified_name(&self) -> Option { - self.project.as_ref().map(|p| QualifiedName { project: p.clone(), name: self.name.clone() }) + let name = self.name.clone(); + self.project.as_ref().map(|p| QualifiedName { project: p.clone(), name }) } /// Get the number of entries. @@ -392,12 +394,7 @@ mod tests { assert_eq!((color.red * 255.0) as u8, 0xaa); assert_eq!((color.green * 255.0) as u8, 0xbb); assert_eq!((color.blue * 255.0) as u8, 0xcc); - let entry_ids = group - .entries - .borrow() - .iter() - .map(|e| e.id().unwrap()) - .collect_vec(); + let entry_ids = group.entries.borrow().iter().map(|e| e.id().unwrap()).collect_vec(); let expected_ids = vec![6, 10, 5]; assert_eq!(entry_ids, expected_ids); } From 3d413097106a1241cff3d24be10e1dac7ce6215d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:13:51 +0200 Subject: [PATCH 040/140] documentation_html pretty --- app/gui/src/controller/searcher.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index ef13c838c4bb..668d34a48c2d 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -60,8 +60,11 @@ thread_local! { // FIXME[MC] return_type: None, imports: vec![], - // FIXME[MC] - documentation_html: Some("This will allow you to enter some text easily."), + documentation_html: Some("

\ + A text input node.

\ +
\ + An empty text. The value can be edited and used as an input for other nodes.\ +
"), method_id: None, // FIXME[MC] possible to fix to use icon::Id? icon: "TextInput".into(), @@ -74,8 +77,11 @@ thread_local! { // FIXME[MC] return_type: None, imports: vec![], - // FIXME[MC] - documentation_html: Some("This will allow you to enter a number easily."), + documentation_html: Some("

\ + A number input node.

\ +
\ + A zero number. The value can be edited and used as an input for other nodes.\ +
"), method_id: None, // FIXME[MC] possible to fix to use icon::Id? icon: "NumberInput".into(), From 60cd65978f0498b1cb80c90f605895582b57754d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:14:14 +0200 Subject: [PATCH 041/140] icon::Id::as_str() --- app/gui/src/controller/searcher.rs | 6 ++---- .../component-group/src/icon/define_macro.rs | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 668d34a48c2d..ba5907afbee5 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -66,8 +66,7 @@ thread_local! { An empty text. The value can be edited and used as an input for other nodes.\ "), method_id: None, - // FIXME[MC] possible to fix to use icon::Id? - icon: "TextInput".into(), + icon: ide_view_component_group::icon::Id::TextInput.as_str().into(), }), Rc::new(component::Virtual { name: "number input", @@ -83,8 +82,7 @@ thread_local! { A zero number. The value can be edited and used as an input for other nodes.\ "), method_id: None, - // FIXME[MC] possible to fix to use icon::Id? - icon: "NumberInput".into(), + icon: ide_view_component_group::icon::Id::NumberInput.as_str().into(), }), ]; } diff --git a/app/gui/view/component-browser/component-group/src/icon/define_macro.rs b/app/gui/view/component-browser/component-group/src/icon/define_macro.rs index 093d88d03712..ad325ba8d11c 100644 --- a/app/gui/view/component-browser/component-group/src/icon/define_macro.rs +++ b/app/gui/view/component-browser/component-group/src/icon/define_macro.rs @@ -98,6 +98,12 @@ macro_rules! define_icons { pub fn for_each(mut f: F) { $(f(Self::$variant);)* } + + pub fn as_str(&self) -> &'static str { + match self { + $(Self::$variant => stringify!($variant),)* + } + } } impl FromStr for Id { From 2477947775eb63641b3b7208b548848f8c48b453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:14:34 +0200 Subject: [PATCH 042/140] cleanup some unnecessary trace --- app/gui/src/presenter/searcher.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 6ad946c5c8cc..96d62c1c0977 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -258,7 +258,6 @@ impl Searcher { list_view.set_local_scope_section <+ action_list_changed.map(f_!(model.create_local_scope_provider().content)); new_input <- list_view.suggestion_accepted.filter_map(f!((e) model.suggestion_accepted(*e))); - trace new_input; graph.set_node_expression <+ new_input; current_docs <- all_with( From 0adc6b561c9342ace265bcb97d916bf7b7f96837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:17:19 +0200 Subject: [PATCH 043/140] cargo fmt + tweaks --- app/gui/src/controller/searcher.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index ba5907afbee5..090e9f27bdc7 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -60,13 +60,15 @@ thread_local! { // FIXME[MC] return_type: None, imports: vec![], - documentation_html: Some("

\ + documentation_html: Some( + "

\ A text input node.

\
\ An empty text. The value can be edited and used as an input for other nodes.\ -
"), +
", + ), method_id: None, - icon: ide_view_component_group::icon::Id::TextInput.as_str().into(), + icon: ide_view_component_group::icon::Id::TextInput.as_str().into(), }), Rc::new(component::Virtual { name: "number input", @@ -76,17 +78,21 @@ thread_local! { // FIXME[MC] return_type: None, imports: vec![], - documentation_html: Some("

\ + documentation_html: Some( + "

\ A number input node.

\
\ A zero number. The value can be edited and used as an input for other nodes.\ -
"), +
", + ), method_id: None, - icon: ide_view_component_group::icon::Id::NumberInput.as_str().into(), + icon: ide_view_component_group::icon::Id::NumberInput.as_str().into(), }), ]; } + + // ============== // === Errors === // ============== From f4ce0df6033a15fbf850a71ef85482e6d5987351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:46:33 +0200 Subject: [PATCH 044/140] can_be_entered refactor --- app/gui/src/controller/searcher/component.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 66d68c5d42a5..23c0245a6ae8 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -144,11 +144,11 @@ impl Component { /// Currently, only modules can be entered, and then the Browser should display content and /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { - if let Kind::FromDb { suggestion, .. } = &self.kind { - suggestion.kind == suggestion_database::entry::Kind::Module - } else { - false - } + use suggestion_database::entry::Kind as SuggestionKind; + matches!( + &self.kind, + Kind::FromDb { suggestion, .. } if suggestion.kind == SuggestionKind::Module + ) } /// Update matching info. From 1147898a2c11a88980eb23f090edc49c6db0f8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 15:55:21 +0200 Subject: [PATCH 045/140] refactor Component::fmt --- app/gui/src/controller/searcher/component.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 23c0245a6ae8..8ba03c9ebc19 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -178,14 +178,14 @@ impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.kind { Kind::FromDb { suggestion, .. } => { - let self_type_not_here = - suggestion.self_type.as_ref().filter(|t| *t != &suggestion.module); + let name = suggestion.name.from_case(Case::Snake).to_case(Case::Lower); + let self_type_ref = suggestion.self_type.as_ref(); + let self_type_not_here = self_type_ref.filter(|t| *t != &suggestion.module); if let Some(self_type) = self_type_not_here { let self_name = self_type.name.from_case(Case::Snake).to_case(Case::Title); - let name = suggestion.name.from_case(Case::Snake).to_case(Case::Lower); write!(f, "{} {}", self_name, name) } else { - write!(f, "{}", suggestion.name.from_case(Case::Snake).to_case(Case::Lower)) + write!(f, "{}", name) } } Kind::Virtual { suggestion } => write!(f, "{}", suggestion.name), From 42f2523d317a4302d6576ae75c61732ede097555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 16:31:15 +0200 Subject: [PATCH 046/140] tweak from_qual_name_and_virt_comps --- app/gui/src/controller/searcher/component/group.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index b872985056ea..4f5219af6468 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -119,17 +119,17 @@ impl Group { pub fn from_qualified_name_and_virtual_components( qualified_name: QualifiedName, - entries: impl IntoIterator>, + components: impl IntoIterator>, ) -> Self { - let components = entries.into_iter().map(Into::into).collect_vec(); + let entries = components.into_iter().map(Into::into).collect_vec(); let group_data = Data { project: Some(qualified_name.project), name: qualified_name.name, color: None, component_id: None, - matched_items: Cell::new(components.len()), - initial_entries_order: components.clone(), - entries: RefCell::new(components), + matched_items: Cell::new(entries.len()), + initial_entries_order: entries.clone(), + entries: RefCell::new(entries), }; Group { data: Rc::new(group_data) } } From ba51d70fd0adf763fac06cd999cc515e1fdac1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 2 Aug 2022 16:49:40 +0200 Subject: [PATCH 047/140] refactor log_group_parsing_error --- app/gui/src/lib.rs | 1 + .../model/execution_context/synchronized.rs | 21 +++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/app/gui/src/lib.rs b/app/gui/src/lib.rs index 4fc4e4b03111..82701a5a8ff9 100644 --- a/app/gui/src/lib.rs +++ b/app/gui/src/lib.rs @@ -40,6 +40,7 @@ #![feature(option_result_contains)] #![feature(trait_alias)] #![feature(result_into_ok_or_err)] +#![feature(result_option_inspect)] #![feature(map_try_insert)] #![feature(assert_matches)] #![feature(cell_filter_map)] diff --git a/app/gui/src/model/execution_context/synchronized.rs b/app/gui/src/model/execution_context/synchronized.rs index d96eb0454b21..d6e06ede3655 100644 --- a/app/gui/src/model/execution_context/synchronized.rs +++ b/app/gui/src/model/execution_context/synchronized.rs @@ -99,24 +99,19 @@ impl ExecutionContext { /// Load the component groups defined in libraries imported into the execution context. async fn load_component_groups(&self) { + let log_group_parsing_error = |err: &failure::Error| { + let msg = iformat!( + "Failed to parse a component group returned by the Engine. The group will not \ + appear in the Favorites section of the Component Browser. Error: {err}" + ); + error!(self.logger, "{msg}"); + }; match self.language_server.get_component_groups(&self.id).await { Ok(ls_response) => { let ls_groups = ls_response.component_groups; let groups = ls_groups .into_iter() - .filter_map(|group| match group.try_into() { - // TODO[MC] consider replacing with: .inspect_err(...).ok() - Ok(g) => Some(g), - Err(err) => { - let msg = iformat!( - "Failed to parse a component group returned by the Engine. The group \ - will not appear in the Favorites section of the Component Browser. \ - Error: {err}" - ); - error!(self.logger, "{msg}"); - None - } - }) + .filter_map(|group| group.try_into().inspect_err(log_group_parsing_error).ok()) .collect(); *self.model.component_groups.borrow_mut() = Rc::new(groups); info!(self.logger, "Loaded component groups."); From a3f9fed7438ee17877a273171e0f858e8bfcca99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 12:32:54 +0200 Subject: [PATCH 048/140] WIP starting to write test --- .../controller/searcher/component/builder.rs | 24 +++++++++++++++++++ .../controller/searcher/component/group.rs | 6 +++++ 2 files changed, 30 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 69f95dfc7ec7..c52bcd860e62 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -447,4 +447,28 @@ mod tests { ]; assert_eq!(favorites, expected); } + + #[test] + fn building_component_list_with_virtual_components_in_favorites() { + let logger = Logger::new("tests::building_component_list_with_favorites"); + let db = mock_suggestion_db(logger); + let mut builder = List::new(); + let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); + let base_project_qn = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let qn_of_group_1 = component::group::QualifiedName::new(base_project_qn, "Group 1"); + let qn_of_group_2 = component::group::QualifiedName::new(base_project_qn, "Group 2"); + let groups = [ + execution_context::ComponentGroup { + project: qn_of_group_1.project.clone(), + name: qn_of_group_1.name.clone(), + color: None, + components: vec![ qn_of_db_entry_0 ], + }, + ]; + builder.set_grouping_and_order_of_favorites(&db, &groups); + let virtual_component_1 = component::Virtual { name: "Virtual Component 1", ..default() }; + let vc1_iter = std::iter::once(Rc::new(virtual_components)); + builder.insert_virtual_components_in_favorites_group(qn_of_group_1.clone(), vc1_iter); + builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); + } } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 4f5219af6468..b1d679d5caca 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -27,6 +27,12 @@ pub struct QualifiedName { pub name: ImString, } +impl QualifiedName { + /// Construct. + fn new(project: project::QualifiedName, name: impl Into) -> Self { + Self { project, name: name.into() } + } + // ============ From 2302445337e15247ac8b52f92fb4183139dda83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 12:50:29 +0200 Subject: [PATCH 049/140] fix to compile --- app/gui/src/controller/searcher/component/builder.rs | 10 +++++++--- app/gui/src/controller/searcher/component/group.rs | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index c52bcd860e62..a50acb21cde4 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -450,13 +450,14 @@ mod tests { #[test] fn building_component_list_with_virtual_components_in_favorites() { + use component::group; let logger = Logger::new("tests::building_component_list_with_favorites"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); let base_project_qn = project::QualifiedName::from_segments("Standard", "Base").unwrap(); - let qn_of_group_1 = component::group::QualifiedName::new(base_project_qn, "Group 1"); - let qn_of_group_2 = component::group::QualifiedName::new(base_project_qn, "Group 2"); + let qn_of_group_1 = group::QualifiedName::new(base_project_qn.clone(), "Group 1"); + let qn_of_group_2 = group::QualifiedName::new(base_project_qn, "Group 2"); let groups = [ execution_context::ComponentGroup { project: qn_of_group_1.project.clone(), @@ -467,8 +468,11 @@ mod tests { ]; builder.set_grouping_and_order_of_favorites(&db, &groups); let virtual_component_1 = component::Virtual { name: "Virtual Component 1", ..default() }; - let vc1_iter = std::iter::once(Rc::new(virtual_components)); + let vc1_iter = std::iter::once(Rc::new(virtual_component_1)); builder.insert_virtual_components_in_favorites_group(qn_of_group_1.clone(), vc1_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); + let list = builder.build(); + let favorites = list.favorites; + assert_eq!(favorites.len(), 1, "Expected 1 group in favorites, got: {:?}.", favorites); } } diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index b1d679d5caca..3e4a5f1603b9 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -29,9 +29,10 @@ pub struct QualifiedName { impl QualifiedName { /// Construct. - fn new(project: project::QualifiedName, name: impl Into) -> Self { + pub fn new(project: project::QualifiedName, name: impl Into) -> Self { Self { project, name: name.into() } } +} From 591bd2cbf84886805e3e164d4d689d51e37b37c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 13:00:35 +0200 Subject: [PATCH 050/140] WIP Component::name() --- app/gui/src/controller/searcher/component.rs | 7 +++++++ app/gui/src/controller/searcher/component/builder.rs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8ba03c9ebc19..c0a5a4bc9207 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -127,6 +127,13 @@ impl Component { self.to_string() } + pub fn name(&self) -> &str { + match &self.kind { + Kind::FromDb { suggestion, .. } => suggestion.name.as_str(), + Kind::Virtual { suggestion } => suggestion.name, + } + } + pub fn id(&self) -> Option { match self.kind { Kind::FromDb { id, .. } => Some(*id), diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index a50acb21cde4..261857a6c107 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -474,5 +474,10 @@ mod tests { let list = builder.build(); let favorites = list.favorites; assert_eq!(favorites.len(), 1, "Expected 1 group in favorites, got: {:?}.", favorites); + let components_names = favorites[0].entries.borrow().iter().map(|c| c.name()).collect_vec(); + // let expected_components_names = vec![ + + // ]; + // assert_eq!(favorite_components_names, expected_components_names); } } From 082ee6d5d596bbeecf4dca9ff8e4976b29518c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 13:01:49 +0200 Subject: [PATCH 051/140] WIP use Component::name() more --- app/gui/src/controller/searcher.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 090e9f27bdc7..aa0d6e735962 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1865,11 +1865,7 @@ pub mod test { format!("{}.{}", entry1.module.project_name.project, entry1.module.name()); assert_eq!(module_group.name, expected_group_name); let entries = module_group.entries.borrow(); - let entry_name = |e: &component::Component| match &e.kind { - component::Kind::FromDb { suggestion, .. } => suggestion.name.clone(), - component::Kind::Virtual { suggestion } => suggestion.name.into(), - }; - assert_matches!(entries.as_slice(), [e1, e2] if entry_name(e1) == entry1.name && entry_name(e2) == entry9.name); + assert_matches!(entries.as_slice(), [e1, e2] if e1.name() == entry1.name && e2.name() == entry9.name); } else { ipanic!("Wrong top modules in Component List: {components.top_modules():?}"); } From 91b8f974ae934e4a10d578ef2e6db72ee0d97f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 14:16:37 +0200 Subject: [PATCH 052/140] actual test --- .../controller/searcher/component/builder.rs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 261857a6c107..c992999986e1 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -458,14 +458,12 @@ mod tests { let base_project_qn = project::QualifiedName::from_segments("Standard", "Base").unwrap(); let qn_of_group_1 = group::QualifiedName::new(base_project_qn.clone(), "Group 1"); let qn_of_group_2 = group::QualifiedName::new(base_project_qn, "Group 2"); - let groups = [ - execution_context::ComponentGroup { - project: qn_of_group_1.project.clone(), - name: qn_of_group_1.name.clone(), - color: None, - components: vec![ qn_of_db_entry_0 ], - }, - ]; + let groups = [execution_context::ComponentGroup { + project: qn_of_group_1.project.clone(), + name: qn_of_group_1.name.clone(), + color: None, + components: vec![qn_of_db_entry_0.clone()], + }]; builder.set_grouping_and_order_of_favorites(&db, &groups); let virtual_component_1 = component::Virtual { name: "Virtual Component 1", ..default() }; let vc1_iter = std::iter::once(Rc::new(virtual_component_1)); @@ -474,10 +472,12 @@ mod tests { let list = builder.build(); let favorites = list.favorites; assert_eq!(favorites.len(), 1, "Expected 1 group in favorites, got: {:?}.", favorites); - let components_names = favorites[0].entries.borrow().iter().map(|c| c.name()).collect_vec(); - // let expected_components_names = vec![ - - // ]; - // assert_eq!(favorite_components_names, expected_components_names); + let entries = favorites[0].entries.borrow(); + let entry_names = entries.iter().map(|c| c.name()).collect_vec(); + let expected_entry_names = vec![ + "Virtual Component 1", + "TopModule1", + ]; + assert_eq!(entry_names, expected_entry_names); } } From ef113762fb8095929024a9cac5156c2616e3308a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 14:37:20 +0200 Subject: [PATCH 053/140] WIP 2nd test --- .../controller/searcher/component/builder.rs | 64 ++++++++++++++----- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index c992999986e1..facc913a5854 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -448,36 +448,68 @@ mod tests { assert_eq!(favorites, expected); } + fn check_names_and_order_of_group_entries(group: &component::Group, expected_names: &[&str]) { + let entries = group.entries.borrow(); + let entry_names = entries.iter().map(|c| c.name()).collect_vec(); + assert_eq!(&entry_names, expected_names); + } + #[test] - fn building_component_list_with_virtual_components_in_favorites() { + fn building_component_list_with_virtual_components_in_existing_favorites_group() { use component::group; - let logger = Logger::new("tests::building_component_list_with_favorites"); + let logger = Logger::new("tests::virtual_components_in_existing_favorites_group"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let base_project_qn = project::QualifiedName::from_segments("Standard", "Base").unwrap(); - let qn_of_group_1 = group::QualifiedName::new(base_project_qn.clone(), "Group 1"); - let qn_of_group_2 = group::QualifiedName::new(base_project_qn, "Group 2"); + let qn_of_base_project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let qn_of_group = group::QualifiedName::new(qn_of_base_project, "Group"); let groups = [execution_context::ComponentGroup { - project: qn_of_group_1.project.clone(), - name: qn_of_group_1.name.clone(), + project: qn_of_group.project.clone(), + name: qn_of_group.name.clone(), color: None, components: vec![qn_of_db_entry_0.clone()], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); - let virtual_component_1 = component::Virtual { name: "Virtual Component 1", ..default() }; - let vc1_iter = std::iter::once(Rc::new(virtual_component_1)); - builder.insert_virtual_components_in_favorites_group(qn_of_group_1.clone(), vc1_iter); + let virtual_component = component::Virtual { name: "Virtual Component", ..default() }; + let vc_iter = std::iter::once(Rc::new(virtual_component)); + builder.insert_virtual_components_in_favorites_group(qn_of_group.clone(), vc_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; - assert_eq!(favorites.len(), 1, "Expected 1 group in favorites, got: {:?}.", favorites); - let entries = favorites[0].entries.borrow(); - let entry_names = entries.iter().map(|c| c.name()).collect_vec(); - let expected_entry_names = vec![ - "Virtual Component 1", + assert_eq!(favorites.len(), 1, "Expected one group of favorites, got: {:?}.", favorites); + let expected_entry_names = [ + "Virtual Component", "TopModule1", ]; - assert_eq!(entry_names, expected_entry_names); + check_names_and_order_of_group_entries(&favorites[0], &expected_entry_names); + } + + #[test] + fn building_component_list_with_virtual_components_in_new_favorites_group() { + use component::group; + let logger = Logger::new("tests::virtual_components_in_new_favorites_group"); + let db = mock_suggestion_db(logger); + let mut builder = List::new(); + let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); + let qn_of_base_project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let qn_of_group_1 = group::QualifiedName::new(qn_of_base_project.clone(), "Group 1"); + let groups = [execution_context::ComponentGroup { + project: qn_of_group_1.project.clone(), + name: qn_of_group_1.name.clone(), + color: None, + components: vec![qn_of_db_entry_0.clone()], + }]; + builder.set_grouping_and_order_of_favorites(&db, &groups); + let virtual_component = component::Virtual { name: "Virtual Component", ..default() }; + let vc_iter = std::iter::once(Rc::new(virtual_component)); + let qn_of_group_2 = group::QualifiedName::new(qn_of_base_project, "Group 2"); + builder.insert_virtual_components_in_favorites_group(qn_of_group_2.clone(), vc_iter); + builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); + let list = builder.build(); + let favorites = list.favorites; + assert_eq!(favorites.len(), 2, "Expected two groups of favorites, got: {:?}.", favorites); + let group_at_0 = &favorites[0]; + assert_eq!(group_at_0.name, "Group 2"); + check_names_and_order_of_group_entries(group_at_0, &["Virtual Component"]); } } From 5e4ddd7e08f21afd04f8f6cbf937af9d97c6ea69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 14:38:37 +0200 Subject: [PATCH 054/140] group_at_1 in test --- app/gui/src/controller/searcher/component/builder.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index facc913a5854..ec73e7a16f8a 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -511,5 +511,8 @@ mod tests { let group_at_0 = &favorites[0]; assert_eq!(group_at_0.name, "Group 2"); check_names_and_order_of_group_entries(group_at_0, &["Virtual Component"]); + let group_at_1 = &favorites[1]; + assert_eq!(group_at_1.name, "Group 1"); + check_names_and_order_of_group_entries(group_at_1, &["TopModule1"]); } } From 9dbc18fb9f4769c35476dfa469edaadde99bfa1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 14:57:36 +0200 Subject: [PATCH 055/140] of_standard_base_library() --- app/gui/controller/double-representation/src/project.rs | 5 +++++ app/gui/src/controller/searcher.rs | 4 +--- app/gui/src/controller/searcher/component/builder.rs | 8 ++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index d9417030df05..8dcc17cb379d 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -76,6 +76,11 @@ impl QualifiedName { } } + /// Return the qualified name of the "Standard.Base" library project. + pub fn of_standard_base_library() -> Self { + Self::from_segments("Standard", "Base").unwrap() + } + /// The iterator over name's segments: the namespace and project name. pub fn segments(&self) -> impl Iterator { std::iter::once(self.namespace.as_ref()).chain(std::iter::once(self.project.as_ref())) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index aa0d6e735962..3335b781d45c 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1230,9 +1230,7 @@ fn component_list_builder_with_favorites<'a>( builder = builder.with_local_scope_module_id(id); } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); - // FIXME[MC]: solve 'unwrap' somehow: make this a thread_local static? validate "Base" at - // comptime? - let project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let project = project::QualifiedName::of_standard_base_library(); let group_name = component::group::QualifiedName { project, name: "Input".into() }; let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); builder.insert_virtual_components_in_favorites_group(group_name, components); diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index ec73e7a16f8a..95853ea9998c 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -404,7 +404,7 @@ mod tests { assert_eq!(db.lookup_by_qualified_name_str(QN_NOT_IN_DB), None); let groups = [ execution_context::ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Group 1".into(), color: None, components: vec![ @@ -418,7 +418,7 @@ mod tests { ], }, execution_context::ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Group 2".into(), color: None, components: vec![ @@ -461,7 +461,7 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let qn_of_base_project = project::QualifiedName::of_standard_base_library(); let qn_of_group = group::QualifiedName::new(qn_of_base_project, "Group"); let groups = [execution_context::ComponentGroup { project: qn_of_group.project.clone(), @@ -491,7 +491,7 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_project = project::QualifiedName::from_segments("Standard", "Base").unwrap(); + let qn_of_base_project = project::QualifiedName::of_standard_base_library(); let qn_of_group_1 = group::QualifiedName::new(qn_of_base_project.clone(), "Group 1"); let groups = [execution_context::ComponentGroup { project: qn_of_group_1.project.clone(), From 844d619bf7ebb577cf7311c6f51678f022dbcb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 14:59:42 +0200 Subject: [PATCH 056/140] use it more --- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/controller/searcher/component/group.rs | 4 ++-- app/gui/src/model/execution_context/synchronized.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index c0a5a4bc9207..41d6245e0117 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -405,7 +405,7 @@ pub(crate) mod tests { ) -> Vec { let db_entries = component_ids.iter().map(|id| db.lookup(*id).unwrap()); let group = crate::model::execution_context::ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Test Group 1".into(), color: None, components: db_entries.into_iter().map(|e| e.qualified_name()).collect(), diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 3e4a5f1603b9..4cb00b820b96 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -379,7 +379,7 @@ mod tests { // order. Some of the names correspond to entries present in the suggestion database, // some do not. let ec_group = execution_context::ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Test Group 1".into(), color: color::Rgb::from_css_hex("#aabbcc"), components: vec![ @@ -413,7 +413,7 @@ mod tests { let logger = Logger::new("tests::constructing_component_group_from_names_not_found_in_db"); let suggestion_db = Rc::new(mock_suggestion_db(logger)); let ec_group = execution_context::ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Input".into(), color: None, components: vec!["NAME.NOT.FOUND.IN.DB".into()], diff --git a/app/gui/src/model/execution_context/synchronized.rs b/app/gui/src/model/execution_context/synchronized.rs index d6e06ede3655..6f9925ac224c 100644 --- a/app/gui/src/model/execution_context/synchronized.rs +++ b/app/gui/src/model/execution_context/synchronized.rs @@ -619,7 +619,7 @@ pub mod test { // Verify that the second component group was parsed and has expected contents. assert_eq!(groups[1], ComponentGroup { - project: project::QualifiedName::from_segments("Standard", "Base").unwrap(), + project: project::QualifiedName::of_standard_base_library(), name: "Input".into(), color: None, components: vec!["Standard.Base.System.File.new".into(),], From 4bbf8fcc228af3554871eb5a406e0f4893626e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 15:02:28 +0200 Subject: [PATCH 057/140] test that qn_of_std_base does not panic --- app/gui/controller/double-representation/src/project.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index 8dcc17cb379d..bfbc6d769eac 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -157,4 +157,9 @@ mod test { invalid_case("namespace."); invalid_case("."); } + + #[test] + fn qualified_name_of_standard_base_library_does_not_panic() { + let _ = QualifiedName::of_standard_base_library(); + } } From 7ed7c9e6416eb7628eb8c770f15715ce1cbcfafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 15:09:05 +0200 Subject: [PATCH 058/140] drop TODO --- app/gui/src/controller/searcher.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 3335b781d45c..14a6f498c14c 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -50,7 +50,6 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; thread_local! { - // TODO[MC]: can it be just slice? `[Rc]` static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = vec![ Rc::new(component::Virtual { name: "text input", From 16e4647c56498a83b61908b0c935c4dfb2cace1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 16:01:28 +0200 Subject: [PATCH 059/140] WIP const_format --- Cargo.lock | 1 + app/gui/Cargo.toml | 1 + app/gui/src/controller/searcher.rs | 68 ++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 812634b2b209..25a9939527b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1960,6 +1960,7 @@ dependencies = [ "ast", "bimap", "console_error_panic_hook", + "const_format", "convert_case 0.5.0", "double-representation", "engine-protocol", diff --git a/app/gui/Cargo.toml b/app/gui/Cargo.toml index 0b40465b420c..a1ce7d25937c 100644 --- a/app/gui/Cargo.toml +++ b/app/gui/Cargo.toml @@ -38,6 +38,7 @@ parser = { path = "language/parser" } span-tree = { path = "language/span-tree" } bimap = { version = "0.4.0" } console_error_panic_hook = { version = "0.1.6" } +const_format = { version = "0.2.22" } convert_case = { version = "0.5.0" } failure = { version = "0.1.6" } flo_stream = { version = "0.4.0" } diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 14a6f498c14c..86b92ea29e13 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -13,6 +13,7 @@ use crate::model::suggestion_database; use crate::model::suggestion_database::entry::CodeToInsert; use crate::notification; +use const_format::concatcp; use double_representation::graph::GraphInfo; use double_representation::graph::LocationHint; use double_representation::module::QualifiedName; @@ -49,6 +50,18 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; /// See also [`Searcher::add_enso_project_entries`]. const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; +macro_rules! doc_html_with_summary_and_synopsis { + ($summary_html:literal, $synopsis_html:literal) => { + concatcp!( + "

", + $summary_html, + "

", + $synopsis_html, + "
" + ) + } +} + thread_local! { static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = vec![ Rc::new(component::Virtual { @@ -56,16 +69,12 @@ thread_local! { code: "\"\"", this_arg: None, argument_types: vec![], - // FIXME[MC] - return_type: None, + return_type: Some("Standard.Base.Data.Text.Text".try_into().unwrap()), imports: vec![], - documentation_html: Some( - "

\ - A text input node.

\ -
\ - An empty text. The value can be edited and used as an input for other nodes.\ -
", - ), + documentation_html: Some(doc_html_with_summary_and_synopsis!( + "A text input node.", + "An empty text. The value can be edited and used as an input for other nodes." + )), method_id: None, icon: ide_view_component_group::icon::Id::TextInput.as_str().into(), }), @@ -74,16 +83,12 @@ thread_local! { code: "0", this_arg: None, argument_types: vec![], - // FIXME[MC] - return_type: None, + return_type: Some("Standard.Base.Data.Numbers.Number".try_into().unwrap()), imports: vec![], - documentation_html: Some( - "

\ - A number input node.

\ -
\ - A zero number. The value can be edited and used as an input for other nodes.\ -
", - ), + documentation_html: Some(doc_html_with_summary_and_synopsis!( + "A number input node.", + "A zero number. The value can be edited and used as an input for other nodes." + )), method_id: None, icon: ide_view_component_group::icon::Id::NumberInput.as_str().into(), }), @@ -92,6 +97,33 @@ thread_local! { +// ================================ +// === ConstantVirtualComponent === +// ================================ + +struct ConstantVirtualComponent { + pub name: &'static str, + pub code: &'static str, + pub return_type: tp::QualifiedName, + pub documentation_html: &'static str, + pub icon: ide_view_component_group::icon::Id, +} + +impl From for component::Virtual { + fn from(constant: ConstantVirtualComponent) -> component::Virtual { + component::Virtual { + name: constant.name, code: constant.code, this_arg: None, argument_types: vec![], + return_type: Some(constant.return_type), + imports: vec![], + documentation_html: Some(constant.documentation_html), + method_id: None, + icon: constant.icon.as_str().into(), + } + } +} + + + // ============== // === Errors === // ============== From 15b483f948992cf2107fa6d3d118d30765dcab46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 16:07:42 +0200 Subject: [PATCH 060/140] VirtCompWithLiteral --- app/gui/src/controller/searcher.rs | 58 +++++++++++++----------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 86b92ea29e13..96c2c3aa7432 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -63,61 +63,53 @@ macro_rules! doc_html_with_summary_and_synopsis { } thread_local! { - static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = vec![ - Rc::new(component::Virtual { + static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = [ + VirtualComponentWithLiteral { name: "text input", code: "\"\"", - this_arg: None, - argument_types: vec![], - return_type: Some("Standard.Base.Data.Text.Text".try_into().unwrap()), - imports: vec![], - documentation_html: Some(doc_html_with_summary_and_synopsis!( + return_type: "Standard.Base.Data.Text.Text", + documentation_html: doc_html_with_summary_and_synopsis!( "A text input node.", "An empty text. The value can be edited and used as an input for other nodes." - )), - method_id: None, - icon: ide_view_component_group::icon::Id::TextInput.as_str().into(), - }), - Rc::new(component::Virtual { + ), + icon: ide_view_component_group::icon::Id::TextInput, + }, + VirtualComponentWithLiteral { name: "number input", code: "0", - this_arg: None, - argument_types: vec![], - return_type: Some("Standard.Base.Data.Numbers.Number".try_into().unwrap()), - imports: vec![], - documentation_html: Some(doc_html_with_summary_and_synopsis!( + return_type: "Standard.Base.Data.Numbers.Number", + documentation_html: doc_html_with_summary_and_synopsis!( "A number input node.", "A zero number. The value can be edited and used as an input for other nodes." - )), - method_id: None, - icon: ide_view_component_group::icon::Id::NumberInput.as_str().into(), - }), - ]; + ), + icon: ide_view_component_group::icon::Id::NumberInput, + }, + ].into_iter().map(|c| Rc::new(c.into())).collect_vec(); } -// ================================ -// === ConstantVirtualComponent === -// ================================ +// =================================== +// === VirtualComponentWithLiteral === +// =================================== -struct ConstantVirtualComponent { +struct VirtualComponentWithLiteral { pub name: &'static str, pub code: &'static str, - pub return_type: tp::QualifiedName, + pub return_type: &'static str, pub documentation_html: &'static str, pub icon: ide_view_component_group::icon::Id, } -impl From for component::Virtual { - fn from(constant: ConstantVirtualComponent) -> component::Virtual { +impl From for component::Virtual { + fn from(literal: VirtualComponentWithLiteral) -> component::Virtual { component::Virtual { - name: constant.name, code: constant.code, this_arg: None, argument_types: vec![], - return_type: Some(constant.return_type), + name: literal.name, code: literal.code, this_arg: None, argument_types: vec![], + return_type: Some(literal.return_type.try_into().unwrap()), imports: vec![], - documentation_html: Some(constant.documentation_html), + documentation_html: Some(literal.documentation_html), method_id: None, - icon: constant.icon.as_str().into(), + icon: literal.icon.as_str().into(), } } } From 1ede8b0014ab81cdb02a063b612b3ca2945b1f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 16:08:03 +0200 Subject: [PATCH 061/140] cargo fmt --- app/gui/src/controller/searcher.rs | 15 +++++++++------ .../src/controller/searcher/component/builder.rs | 5 +---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 96c2c3aa7432..bb1b911a6b20 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -59,7 +59,7 @@ macro_rules! doc_html_with_summary_and_synopsis { $synopsis_html, "" ) - } + }; } thread_local! { @@ -104,12 +104,15 @@ struct VirtualComponentWithLiteral { impl From for component::Virtual { fn from(literal: VirtualComponentWithLiteral) -> component::Virtual { component::Virtual { - name: literal.name, code: literal.code, this_arg: None, argument_types: vec![], - return_type: Some(literal.return_type.try_into().unwrap()), - imports: vec![], + name: literal.name, + code: literal.code, + this_arg: None, + argument_types: vec![], + return_type: Some(literal.return_type.try_into().unwrap()), + imports: vec![], documentation_html: Some(literal.documentation_html), - method_id: None, - icon: literal.icon.as_str().into(), + method_id: None, + icon: literal.icon.as_str().into(), } } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 95853ea9998c..31e011e04788 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -477,10 +477,7 @@ mod tests { let list = builder.build(); let favorites = list.favorites; assert_eq!(favorites.len(), 1, "Expected one group of favorites, got: {:?}.", favorites); - let expected_entry_names = [ - "Virtual Component", - "TopModule1", - ]; + let expected_entry_names = ["Virtual Component", "TopModule1"]; check_names_and_order_of_group_entries(&favorites[0], &expected_entry_names); } From 8a331de1eff432bd1c8ea2c213962f8e9a8b3266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 4 Aug 2022 16:22:50 +0200 Subject: [PATCH 062/140] fix clippy --- app/gui/src/presenter/searcher/provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index 1961feb4f5c8..9670b0e22ce0 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -207,7 +207,7 @@ impl list_view::entry::ModelProvider for Component } component::Kind::Virtual { suggestion } => { let icon = &suggestion.icon; - let parsed_icon = component_group_view::icon::Id::from_str(&icon); + let parsed_icon = component_group_view::icon::Id::from_str(icon); parsed_icon.unwrap_or_else(|_| { event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); default() From 2ab03df20cc543d9cad16414731f4093af097ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 11:43:48 +0200 Subject: [PATCH 063/140] s//LiteralVirtualComponent --- app/gui/src/controller/searcher.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 1a60ca370351..98514b96cd07 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -64,7 +64,7 @@ macro_rules! doc_html_with_summary_and_synopsis { thread_local! { static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = [ - VirtualComponentWithLiteral { + LiteralVirtualComponent { name: "text input", code: "\"\"", return_type: "Standard.Base.Data.Text.Text", @@ -74,7 +74,7 @@ thread_local! { ), icon: ide_view_component_group::icon::Id::TextInput, }, - VirtualComponentWithLiteral { + LiteralVirtualComponent { name: "number input", code: "0", return_type: "Standard.Base.Data.Numbers.Number", @@ -89,11 +89,11 @@ thread_local! { -// =================================== -// === VirtualComponentWithLiteral === -// =================================== +// =============================== +// === LiteralVirtualComponent === +// =============================== -struct VirtualComponentWithLiteral { +struct LiteralVirtualComponent { pub name: &'static str, pub code: &'static str, pub return_type: &'static str, @@ -101,8 +101,8 @@ struct VirtualComponentWithLiteral { pub icon: ide_view_component_group::icon::Id, } -impl From for component::Virtual { - fn from(literal: VirtualComponentWithLiteral) -> component::Virtual { +impl From for component::Virtual { + fn from(literal: LiteralVirtualComponent) -> component::Virtual { component::Virtual { name: literal.name, code: literal.code, From c8c130b2636b7d67f7c22df02d998b674fb051df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:06:52 +0200 Subject: [PATCH 064/140] INPUT_LITERAL_VIRTUAL_COMPONENTS --- app/gui/src/controller/searcher.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 98514b96cd07..2b9a1f57da6a 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -63,7 +63,9 @@ macro_rules! doc_html_with_summary_and_synopsis { } thread_local! { - static VIRTUAL_COMPONENTS_IN_INPUT_GROUP: Vec> = [ + /// Virtual components with literal values, documented as input nodes. When added into the + /// [`component::List`] they help the users discover how to enter literals in code. + static INPUT_LITERAL_VIRTUAL_COMPONENTS: Vec> = [ LiteralVirtualComponent { name: "text input", code: "\"\"", @@ -1259,8 +1261,9 @@ fn component_list_builder_with_favorites<'a>( builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let project = project::QualifiedName::of_standard_base_library(); let group_name = component::group::QualifiedName { project, name: "Input".into() }; - let components = VIRTUAL_COMPONENTS_IN_INPUT_GROUP.with(|c| c.clone()); - builder.insert_virtual_components_in_favorites_group(group_name, components); + let group_qn = component::group::QualifiedName { project, name: group_name }; + let components = INPUT_LITERAL_VIRTUAL_COMPONENTS.with(|c| c.clone()); + builder.insert_virtual_components_in_favorites_group(group_qn, components); builder } From 58acf499926c615539567db52bb78d0278f44c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:07:01 +0200 Subject: [PATCH 065/140] INPUT_COMPONENT_GROUP_NAME --- app/gui/src/controller/searcher.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 2b9a1f57da6a..b6702314ceaf 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -50,6 +50,10 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; /// See also [`Searcher::add_enso_project_entries`]. const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; +/// Name of the virtual component group in the `Standard.Base` library which contains input +/// components. +const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; + macro_rules! doc_html_with_summary_and_synopsis { ($summary_html:literal, $synopsis_html:literal) => { concatcp!( @@ -1260,7 +1264,7 @@ fn component_list_builder_with_favorites<'a>( } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let project = project::QualifiedName::of_standard_base_library(); - let group_name = component::group::QualifiedName { project, name: "Input".into() }; + let group_name = INPUT_COMPONENT_GROUP_NAME.into(); let group_qn = component::group::QualifiedName { project, name: group_name }; let components = INPUT_LITERAL_VIRTUAL_COMPONENTS.with(|c| c.clone()); builder.insert_virtual_components_in_favorites_group(group_qn, components); From 771338cea7a88f83ee8b2cc8c1f6b4de4230d3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:20:44 +0200 Subject: [PATCH 066/140] less
s in html --- app/gui/src/controller/searcher.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index b6702314ceaf..e70e1fea69a7 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -59,9 +59,9 @@ macro_rules! doc_html_with_summary_and_synopsis { concatcp!( "

", $summary_html, - "

", + "
", $synopsis_html, - "
" + "
" ) }; } From cdd042c6cabac67b987034ae1e8e81aa3ed4ad69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:21:05 +0200 Subject: [PATCH 067/140] rename html macro --- app/gui/src/controller/searcher.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index e70e1fea69a7..095592a7fa48 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -54,7 +54,7 @@ const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; /// components. const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; -macro_rules! doc_html_with_summary_and_synopsis { +macro_rules! html_docs_with_summary_and_synopsis { ($summary_html:literal, $synopsis_html:literal) => { concatcp!( "

", @@ -74,7 +74,7 @@ thread_local! { name: "text input", code: "\"\"", return_type: "Standard.Base.Data.Text.Text", - documentation_html: doc_html_with_summary_and_synopsis!( + documentation_html: html_docs_with_summary_and_synopsis!( "A text input node.", "An empty text. The value can be edited and used as an input for other nodes." ), @@ -84,7 +84,7 @@ thread_local! { name: "number input", code: "0", return_type: "Standard.Base.Data.Numbers.Number", - documentation_html: doc_html_with_summary_and_synopsis!( + documentation_html: html_docs_with_summary_and_synopsis!( "A number input node.", "A zero number. The value can be edited and used as an input for other nodes." ), From db91d0d7b22d687ae48a1bd96b8d60931848558f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:24:32 +0200 Subject: [PATCH 068/140] doc for LiteralVC --- app/gui/src/controller/searcher.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 095592a7fa48..caefa465242f 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -99,6 +99,7 @@ thread_local! { // === LiteralVirtualComponent === // =============================== +/// A virtual component containing a literal value in its code. struct LiteralVirtualComponent { pub name: &'static str, pub code: &'static str, From ae5cd0c7da102e41f6d3bab75418f5ea3ae0e42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:31:01 +0200 Subject: [PATCH 069/140] rename local vars in comp_list_builder_w_favs --- app/gui/src/controller/searcher.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index caefa465242f..7ad36ee52275 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1264,11 +1264,11 @@ fn component_list_builder_with_favorites<'a>( builder = builder.with_local_scope_module_id(id); } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); - let project = project::QualifiedName::of_standard_base_library(); - let group_name = INPUT_COMPONENT_GROUP_NAME.into(); - let group_qn = component::group::QualifiedName { project, name: group_name }; + let base_lib_qn = project::QualifiedName::of_standard_base_library(); + let input_group_name = INPUT_COMPONENT_GROUP_NAME; + let input_group_qn = component::group::QualifiedName::new(base_lib_qn, input_group_name); let components = INPUT_LITERAL_VIRTUAL_COMPONENTS.with(|c| c.clone()); - builder.insert_virtual_components_in_favorites_group(group_qn, components); + builder.insert_virtual_components_in_favorites_group(input_group_qn, components); builder } From ee3dc7459984802691457f0a70c8bc06d2f84ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:37:12 +0200 Subject: [PATCH 070/140] doc for component::Virtual --- app/gui/src/controller/searcher/component.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8b571bf112fc..cb883f36afb8 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -30,6 +30,7 @@ pub type Id = suggestion_database::entry::Id; /// Information how the component matches the filtering pattern. pub type MatchInfo = controller::searcher::action::MatchInfo; +/// A virtual component is not present in the [`suggestion_database`] but hardcoded instead. pub type Virtual = controller::searcher::action::hardcoded::Suggestion; From f28ddf63149f16583053d195fe2f3a05e099049b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:37:54 +0200 Subject: [PATCH 071/140] tweak compo::Virtual doc --- app/gui/src/controller/searcher/component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index cb883f36afb8..ce79415d1a2b 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -30,7 +30,7 @@ pub type Id = suggestion_database::entry::Id; /// Information how the component matches the filtering pattern. pub type MatchInfo = controller::searcher::action::MatchInfo; -/// A virtual component is not present in the [`suggestion_database`] but hardcoded instead. +/// A virtual component is hardcoded and not present in the [`suggestion_database`]. pub type Virtual = controller::searcher::action::hardcoded::Suggestion; From a77afe3fc39ff2e3857e4445e46002a8958940b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 12:46:19 +0200 Subject: [PATCH 072/140] docs for Kind --- app/gui/src/controller/searcher/component.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index ce79415d1a2b..7dadf8a5c773 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -60,10 +60,21 @@ pub enum Order { // === Kind === // ============ +/// The kind of the suggestion offered by a [`Component`]. #[derive(Clone, CloneRef, Debug)] pub enum Kind { - FromDb { id: Immutable, suggestion: Rc }, - Virtual { suggestion: Rc }, + /// A suggestion from the [`suggestion_database`]. + FromDb { + /// The ID of the suggestion in the [`suggestion_database`]. + id: Immutable, + /// The contents of the suggestion. + suggestion: Rc, + }, + /// A virtual (hardcoded) suggestion. + Virtual { + /// The contents of the suggestion. + suggestion: Rc, + }, } From 25c12e943c186cfbdf7aef4c497bb17d92bea3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:05:19 +0200 Subject: [PATCH 073/140] Snippet & .entry --- app/gui/src/controller/searcher.rs | 29 +++++------ app/gui/src/controller/searcher/component.rs | 48 +++++++++---------- .../controller/searcher/component/builder.rs | 13 +++-- .../controller/searcher/component/group.rs | 4 +- app/gui/src/presenter/searcher.rs | 20 ++++---- app/gui/src/presenter/searcher/provider.rs | 10 ++-- 6 files changed, 62 insertions(+), 62 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 7ad36ee52275..027d2d83d16b 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -67,10 +67,11 @@ macro_rules! html_docs_with_summary_and_synopsis { } thread_local! { - /// Virtual components with literal values, documented as input nodes. When added into the - /// [`component::List`] they help the users discover how to enter literals in code. - static INPUT_LITERAL_VIRTUAL_COMPONENTS: Vec> = [ - LiteralVirtualComponent { + /// Code snippets of default literal values of text and number type. The snippets are + /// documented as code that can be used as input nodes. When converted to [`Component`]s and + /// added to the [`component::List`] they allow the users to easily enter literals in code. + static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ + LiteralSnippet { name: "text input", code: "\"\"", return_type: "Standard.Base.Data.Text.Text", @@ -80,7 +81,7 @@ thread_local! { ), icon: ide_view_component_group::icon::Id::TextInput, }, - LiteralVirtualComponent { + LiteralSnippet { name: "number input", code: "0", return_type: "Standard.Base.Data.Numbers.Number", @@ -95,12 +96,12 @@ thread_local! { -// =============================== -// === LiteralVirtualComponent === -// =============================== +// ====================== +// === LiteralSnippet === +// ====================== /// A virtual component containing a literal value in its code. -struct LiteralVirtualComponent { +struct LiteralSnippet { pub name: &'static str, pub code: &'static str, pub return_type: &'static str, @@ -108,9 +109,9 @@ struct LiteralVirtualComponent { pub icon: ide_view_component_group::icon::Id, } -impl From for component::Virtual { - fn from(literal: LiteralVirtualComponent) -> component::Virtual { - component::Virtual { +impl From for component::HardcodedSnippet { + fn from(literal: LiteralSnippet) -> component::HardcodedSnippet { + component::HardcodedSnippet { name: literal.name, code: literal.code, this_arg: None, @@ -1267,8 +1268,8 @@ fn component_list_builder_with_favorites<'a>( let base_lib_qn = project::QualifiedName::of_standard_base_library(); let input_group_name = INPUT_COMPONENT_GROUP_NAME; let input_group_qn = component::group::QualifiedName::new(base_lib_qn, input_group_name); - let components = INPUT_LITERAL_VIRTUAL_COMPONENTS.with(|c| c.clone()); - builder.insert_virtual_components_in_favorites_group(input_group_qn, components); + let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|c| c.clone()); + builder.insert_virtual_components_in_favorites_group(input_group_qn, snippets); builder } diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 7dadf8a5c773..7f1627431dec 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -30,8 +30,8 @@ pub type Id = suggestion_database::entry::Id; /// Information how the component matches the filtering pattern. pub type MatchInfo = controller::searcher::action::MatchInfo; -/// A virtual component is hardcoded and not present in the [`suggestion_database`]. -pub type Virtual = controller::searcher::action::hardcoded::Suggestion; +/// A hardcoded snippet of code with a description and syntactic metadata. +pub type HardcodedSnippet = controller::searcher::action::hardcoded::Suggestion; // ============= @@ -60,20 +60,20 @@ pub enum Order { // === Kind === // ============ -/// The kind of the suggestion offered by a [`Component`]. +/// The kind of a [`Component`]. #[derive(Clone, CloneRef, Debug)] pub enum Kind { - /// A suggestion from the [`suggestion_database`]. + /// A component from the [`suggestion_database`]. FromDb { - /// The ID of the suggestion in the [`suggestion_database`]. + /// The ID of the component in the [`suggestion_database`]. id: Immutable, - /// The contents of the suggestion. - suggestion: Rc, + /// The component's entry in the [`suggestion_database`]. + entry: Rc, }, - /// A virtual (hardcoded) suggestion. + /// A virtual component contains a hardcoded snippet of code. Virtual { - /// The contents of the suggestion. - suggestion: Rc, + /// A hardcoded snippet of code. + snippet: Rc, }, } @@ -102,8 +102,8 @@ impl Component { /// Construct a new component. /// /// The matching info will be filled for an empty pattern. - pub fn new(id: Id, suggestion: Rc) -> Self { - let kind = Kind::FromDb { id: Immutable(id), suggestion }; + pub fn new(id: Id, entry: Rc) -> Self { + let kind = Kind::FromDb { id: Immutable(id), entry }; Self { kind, match_info: default() } } @@ -114,8 +114,8 @@ impl Component { pub fn name(&self) -> &str { match &self.kind { - Kind::FromDb { suggestion, .. } => suggestion.name.as_str(), - Kind::Virtual { suggestion } => suggestion.name, + Kind::FromDb { entry, .. } => entry.name.as_str(), + Kind::Virtual { snippet } => snippet.name, } } @@ -136,10 +136,10 @@ impl Component { /// Currently, only modules can be entered, and then the Browser should display content and /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { - use suggestion_database::entry::Kind as SuggestionKind; + use suggestion_database::entry::Kind as EntryKind; matches!( &self.kind, - Kind::FromDb { suggestion, .. } if suggestion.kind == SuggestionKind::Module + Kind::FromDb { entry, .. } if entry.kind == EntryKind::Module ) } @@ -160,19 +160,19 @@ impl Component { } } -impl From> for Component { - fn from(suggestion: Rc) -> Self { - Self { kind: Kind::Virtual { suggestion }, match_info: default() } +impl From> for Component { + fn from(snippet: Rc) -> Self { + Self { kind: Kind::Virtual { snippet }, match_info: default() } } } impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.kind { - Kind::FromDb { suggestion, .. } => { - let name = suggestion.name.from_case(Case::Snake).to_case(Case::Lower); - let self_type_ref = suggestion.self_type.as_ref(); - let self_type_not_here = self_type_ref.filter(|t| *t != &suggestion.module); + Kind::FromDb { entry, .. } => { + let name = entry.name.from_case(Case::Snake).to_case(Case::Lower); + let self_type_ref = entry.self_type.as_ref(); + let self_type_not_here = self_type_ref.filter(|t| *t != &entry.module); if let Some(self_type) = self_type_not_here { let self_name = self_type.name.from_case(Case::Snake).to_case(Case::Title); write!(f, "{} {}", self_name, name) @@ -180,7 +180,7 @@ impl Display for Component { write!(f, "{}", name) } } - Kind::Virtual { suggestion } => write!(f, "{}", suggestion.name), + Kind::Virtual { snippet } => write!(f, "{}", snippet.name), } } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 31e011e04788..0ea73caa649e 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -120,17 +120,17 @@ impl List { let lookup_component_by_id = |id| Some(Component::new(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { - if let component::Kind::FromDb { id, ref suggestion } = component.kind { + if let component::Kind::FromDb { id, ref entry } = component.kind { self.allowed_favorites.insert(*id); let mut component_inserted_somewhere = false; - if let Some(parent_module) = suggestion.parent_module() { + if let Some(parent_module) = entry.parent_module() { if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { parent_group.content.entries.borrow_mut().push(component.clone_ref()); component_inserted_somewhere = true; let parent_id = parent_group.content.component_id; let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); - let not_module = suggestion.kind != Kind::Module; + let not_module = entry.kind != Kind::Module; if in_local_scope && not_module { self.local_scope.entries.borrow_mut().push(component.clone_ref()); } @@ -172,7 +172,7 @@ impl List { pub fn insert_virtual_components_in_favorites_group( &mut self, group_name: component::group::QualifiedName, - virtual_components: impl IntoIterator>, + snippets: impl IntoIterator>, ) { use component::Group; let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); @@ -180,10 +180,9 @@ impl List { .iter_mut() .find(|g| g.qualified_name().as_ref() == Some(&group_name)); if let Some(group) = group_with_matching_name { - group.insert_entries(&virtual_components.into_iter().map(Into::into).collect_vec()); + group.insert_entries(&snippets.into_iter().map(Into::into).collect_vec()); } else { - let group = - Group::from_qualified_name_and_virtual_components(group_name, virtual_components); + let group = Group::from_qualified_name_and_virtual_components(group_name, snippets); favorites_grouping.insert(0, group); } self.grouping_and_order_of_favorites = component::group::List::new(favorites_grouping); diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 573c34984e86..05f5cf9c72f6 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -124,9 +124,9 @@ impl Group { pub fn from_qualified_name_and_virtual_components( qualified_name: QualifiedName, - components: impl IntoIterator>, + snippets: impl IntoIterator>, ) -> Self { - let entries = components.into_iter().map(Into::into).collect_vec(); + let entries = snippets.into_iter().map(Into::into).collect_vec(); let group_data = Data { project: Some(qualified_name.project), name: qualified_name.name, diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 418a2f629193..19bba47a4b9c 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -136,10 +136,10 @@ impl Model { self.component_by_view_id(id).ok_or_else(|| NoSuchComponent(id).into()); let new_code = component.and_then(|component| { let suggestion = match component.kind { - component::Kind::FromDb { suggestion, .. } => - Suggestion::FromDatabase(suggestion.clone_ref()), - component::Kind::Virtual { suggestion } => - Suggestion::Hardcoded(suggestion.clone_ref()), + component::Kind::FromDb { entry, .. } => + Suggestion::FromDatabase(entry.clone_ref()), + component::Kind::Virtual { snippet } => + Suggestion::Hardcoded(snippet.clone_ref()), }; self.controller.use_suggestion(suggestion) }); @@ -208,16 +208,16 @@ impl Model { let component = id.and_then(|id| self.component_by_view_id(id)); if let Some(component) = component { match component.kind { - component::Kind::FromDb { suggestion, .. } => { - if let Some(documentation) = &suggestion.documentation_html { - let title = title_for_docs(&suggestion); + component::Kind::FromDb { entry, .. } => { + if let Some(documentation) = &entry.documentation_html { + let title = title_for_docs(&entry); format!("

{title}

{documentation}") } else { - doc_placeholder_for(&suggestion) + doc_placeholder_for(&entry) } } - component::Kind::Virtual { suggestion } => { - if let Some(documentation) = &suggestion.documentation_html { + component::Kind::Virtual { snippet } => { + if let Some(documentation) = &snippet.documentation_html { documentation.to_string() } else { default() diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index a3186c19eba9..f55c2731744c 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -188,14 +188,14 @@ impl list_view::entry::ModelProvider for Component let label = component.label(); let highlighted = bytes_of_matched_letters(&*match_info, &label); let icon = match component.kind { - component::Kind::FromDb { suggestion, .. } => { - let kind = suggestion.kind; - let icon_name = suggestion.icon_name.as_ref(); + component::Kind::FromDb { entry, .. } => { + let kind = entry.kind; + let icon_name = entry.icon_name.as_ref(); let icon = icon_name.and_then(|n| n.to_pascal_case().parse().ok()); icon.unwrap_or_else(|| for_each_kind_variant!(kind_to_icon(kind))) } - component::Kind::Virtual { suggestion } => { - let icon = &suggestion.icon; + component::Kind::Virtual { snippet } => { + let icon = &snippet.icon; let parsed_icon = component_group_view::icon::Id::from_str(icon); parsed_icon.unwrap_or_else(|_| { event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); From 2940e31ab9a0b19d8dc95d3ff6f806e79a70c945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:05:42 +0200 Subject: [PATCH 074/140] new_from_db --- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/controller/searcher/component/builder.rs | 2 +- app/gui/src/controller/searcher/component/group.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 7f1627431dec..b4d832a9ecc6 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -102,7 +102,7 @@ impl Component { /// Construct a new component. /// /// The matching info will be filled for an empty pattern. - pub fn new(id: Id, entry: Rc) -> Self { + pub fn new_from_db(id: Id, entry: Rc) -> Self { let kind = Kind::FromDb { id: Immutable(id), entry }; Self { kind, match_info: default() } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 0ea73caa649e..e5a1f6dbaeeb 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -117,7 +117,7 @@ impl List { ) { use suggestion_database::entry::Kind; let local_scope_id = self.local_scope.component_id; - let lookup_component_by_id = |id| Some(Component::new(id, db.lookup(id).ok()?)); + let lookup_component_by_id = |id| Some(Component::new_from_db(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { if let component::Kind::FromDb { id, ref entry } = component.kind { diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 05f5cf9c72f6..608693810b7c 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -149,7 +149,7 @@ impl Group { ) -> Option { let lookup_component = |qualified_name| { let (id, suggestion) = suggestion_db.lookup_by_qualified_name(qualified_name)?; - Some(Component::new(id, suggestion)) + Some(Component::new_from_db(id, suggestion)) }; let components = &group.components; let looked_up_components = components.iter().filter_map(lookup_component).collect_vec(); From a81c20be24b10e22cb1d00229000babdede9e268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:05:52 +0200 Subject: [PATCH 075/140] docs --- app/gui/src/controller/searcher/component/builder.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index e5a1f6dbaeeb..95f7d0185774 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -9,9 +9,10 @@ //! //! When using the methods of the [`List`] type to build a [`component::List`]: //! - The components and groups are sorted once. -//! - The [`component::List::favorites`] contain only components with IDs that were passed both to -//! [`List::set_grouping_and_order_of_favorites`] and to -//! [`List::extend_list_and_allow_favorites_with_ids`]. +//! - The [`component::List::favorites`] will contain: +//! - components with IDs that were passed both to [`List::set_grouping_and_order_of_favorites`] +//! and to [`List::extend_list_and_allow_favorites_with_ids`], +//! - virtual components inserted with [`List::insert_virtual_components_in_favorites_group`]. //! - Empty component groups are allowed in favorites. (This simplifies distributing groups of //! favorites over columns in [Component Browser](crate::controller::Searcher) consistently. //! That's because for the same input to [`List::set_grouping_and_order_of_favorites`], the same @@ -169,6 +170,9 @@ impl List { std::mem::take(&mut self.grouping_and_order_of_favorites).into_iter().collect_vec() } + /// Insert virtual components at the beginning of a favorites group with given name. If a group + /// with that name does not exist, it is created. The virtual components are created from the + /// given snippets. pub fn insert_virtual_components_in_favorites_group( &mut self, group_name: component::group::QualifiedName, From a23cebad9a22acccceebde805c636bf7a03835ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:06:08 +0200 Subject: [PATCH 076/140] avoid multiline expr --- app/gui/src/controller/searcher/component/builder.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 95f7d0185774..533fae032f92 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -180,9 +180,8 @@ impl List { ) { use component::Group; let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); - let group_with_matching_name = favorites_grouping - .iter_mut() - .find(|g| g.qualified_name().as_ref() == Some(&group_name)); + let name_match = |g: &&mut Group| g.qualified_name().as_ref() == Some(&group_name); + let group_with_matching_name = favorites_grouping.iter_mut().find(name_match); if let Some(group) = group_with_matching_name { group.insert_entries(&snippets.into_iter().map(Into::into).collect_vec()); } else { From 0a66c9d910f3fbc3b581a5b63528dce8109039d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:09:18 +0200 Subject: [PATCH 077/140] tweak LiteralSnippet comment --- app/gui/src/controller/searcher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 027d2d83d16b..03d01cd8c5a5 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -100,7 +100,7 @@ thread_local! { // === LiteralSnippet === // ====================== -/// A virtual component containing a literal value in its code. +/// A snippet of code with a literal value, with description and syntax metadata. struct LiteralSnippet { pub name: &'static str, pub code: &'static str, From 2705eb09241b4202b7985499e18f1239cadba78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:12:32 +0200 Subject: [PATCH 078/140] FromDb -> FromDatabase --- app/gui/src/controller/searcher/component.rs | 12 ++++++------ app/gui/src/controller/searcher/component/builder.rs | 10 +++++++--- app/gui/src/presenter/searcher.rs | 4 ++-- app/gui/src/presenter/searcher/provider.rs | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index b4d832a9ecc6..166536f65108 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -64,7 +64,7 @@ pub enum Order { #[derive(Clone, CloneRef, Debug)] pub enum Kind { /// A component from the [`suggestion_database`]. - FromDb { + FromDatabase { /// The ID of the component in the [`suggestion_database`]. id: Immutable, /// The component's entry in the [`suggestion_database`]. @@ -103,7 +103,7 @@ impl Component { /// /// The matching info will be filled for an empty pattern. pub fn new_from_db(id: Id, entry: Rc) -> Self { - let kind = Kind::FromDb { id: Immutable(id), entry }; + let kind = Kind::FromDatabase { id: Immutable(id), entry }; Self { kind, match_info: default() } } @@ -114,14 +114,14 @@ impl Component { pub fn name(&self) -> &str { match &self.kind { - Kind::FromDb { entry, .. } => entry.name.as_str(), + Kind::FromDatabase { entry, .. } => entry.name.as_str(), Kind::Virtual { snippet } => snippet.name, } } pub fn id(&self) -> Option { match self.kind { - Kind::FromDb { id, .. } => Some(*id), + Kind::FromDatabase { id, .. } => Some(*id), Kind::Virtual { .. } => None, } } @@ -139,7 +139,7 @@ impl Component { use suggestion_database::entry::Kind as EntryKind; matches!( &self.kind, - Kind::FromDb { entry, .. } if entry.kind == EntryKind::Module + Kind::FromDatabase { entry, .. } if entry.kind == EntryKind::Module ) } @@ -169,7 +169,7 @@ impl From> for Component { impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.kind { - Kind::FromDb { entry, .. } => { + Kind::FromDatabase { entry, .. } => { let name = entry.name.from_case(Case::Snake).to_case(Case::Lower); let self_type_ref = entry.self_type.as_ref(); let self_type_not_here = self_type_ref.filter(|t| *t != &entry.module); diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 533fae032f92..9c90ddd2d663 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -121,7 +121,7 @@ impl List { let lookup_component_by_id = |id| Some(Component::new_from_db(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { - if let component::Kind::FromDb { id, ref entry } = component.kind { + if let component::Kind::FromDatabase { id, ref entry } = component.kind { self.allowed_favorites.insert(*id); let mut component_inserted_somewhere = false; if let Some(parent_module) = entry.parent_module() { @@ -148,7 +148,11 @@ impl List { self.all_components.push(component); } } else { - event!(ERROR, "The suggestion database returned a component of a non-FromDb kind: {component:?}"); + let msg = iformat!( + "The suggestion database returned a component of a non-FromDatabase kind: " + component;? + ); + event!(ERROR, "{msg}"); } } } @@ -249,7 +253,7 @@ impl List { let mut favorites_groups = self.take_grouping_and_order_of_favorites_as_vec(); for group in favorites_groups.iter_mut() { group.retain_entries(|e| match e.kind { - component::Kind::FromDb { id, .. } => self.allowed_favorites.contains(&id), + component::Kind::FromDatabase { id, .. } => self.allowed_favorites.contains(&id), component::Kind::Virtual { .. } => true, }); self.all_components.extend(group.entries.borrow().iter().cloned()); diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 19bba47a4b9c..5b6f2027392a 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -136,7 +136,7 @@ impl Model { self.component_by_view_id(id).ok_or_else(|| NoSuchComponent(id).into()); let new_code = component.and_then(|component| { let suggestion = match component.kind { - component::Kind::FromDb { entry, .. } => + component::Kind::FromDatabase { entry, .. } => Suggestion::FromDatabase(entry.clone_ref()), component::Kind::Virtual { snippet } => Suggestion::Hardcoded(snippet.clone_ref()), @@ -208,7 +208,7 @@ impl Model { let component = id.and_then(|id| self.component_by_view_id(id)); if let Some(component) = component { match component.kind { - component::Kind::FromDb { entry, .. } => { + component::Kind::FromDatabase { entry, .. } => { if let Some(documentation) = &entry.documentation_html { let title = title_for_docs(&entry); format!("

{title}

{documentation}") diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index f55c2731744c..e4f2e3594d1a 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -188,7 +188,7 @@ impl list_view::entry::ModelProvider for Component let label = component.label(); let highlighted = bytes_of_matched_letters(&*match_info, &label); let icon = match component.kind { - component::Kind::FromDb { entry, .. } => { + component::Kind::FromDatabase { entry, .. } => { let kind = entry.kind; let icon_name = entry.icon_name.as_ref(); let icon = icon_name.and_then(|n| n.to_pascal_case().parse().ok()); From ef29792eacb18de542f4d319fce46b62ed14a842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:14:05 +0200 Subject: [PATCH 079/140] contain/s/ing --- app/gui/src/controller/searcher/component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 166536f65108..017ca64b8dc1 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -70,7 +70,7 @@ pub enum Kind { /// The component's entry in the [`suggestion_database`]. entry: Rc, }, - /// A virtual component contains a hardcoded snippet of code. + /// A virtual component containing a hardcoded snippet of code. Virtual { /// A hardcoded snippet of code. snippet: Rc, From efafbbcecb604382fc60284c58660addc286e2c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:15:23 +0200 Subject: [PATCH 080/140] new_from_db doc --- app/gui/src/controller/searcher/component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 017ca64b8dc1..c83777f3a92c 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -99,7 +99,7 @@ pub struct Component { } impl Component { - /// Construct a new component. + /// Construct a new component from a [`suggestion_database`] entry. /// /// The matching info will be filled for an empty pattern. pub fn new_from_db(id: Id, entry: Rc) -> Self { From 1b7238025b1aa6597d4acae45cb6fea5ae841bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:17:14 +0200 Subject: [PATCH 081/140] docs for getters --- app/gui/src/controller/searcher/component.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index c83777f3a92c..125953237d25 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -112,6 +112,7 @@ impl Component { self.to_string() } + /// The name of the component. pub fn name(&self) -> &str { match &self.kind { Kind::FromDatabase { entry, .. } => entry.name.as_str(), @@ -119,6 +120,7 @@ impl Component { } } + /// The [`Id`] of the component in the [`suggestion_database`]. pub fn id(&self) -> Option { match self.kind { Kind::FromDatabase { id, .. } => Some(*id), From fffc0609adbc258b3b3ddf267e87e3f4b9c7124c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:18:32 +0200 Subject: [PATCH 082/140] shorten macro call line --- app/gui/src/controller/searcher/component.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 125953237d25..623e5b47d3cc 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -139,10 +139,7 @@ impl Component { /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { use suggestion_database::entry::Kind as EntryKind; - matches!( - &self.kind, - Kind::FromDatabase { entry, .. } if entry.kind == EntryKind::Module - ) + matches!(&self.kind, Kind::FromDatabase { entry, .. } if entry.kind == EntryKind::Module) } /// Update matching info. From ec9b075075ccb7a0e349d87426e4311eeff7bfe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:21:22 +0200 Subject: [PATCH 083/140] entry_name in impl Display --- app/gui/src/controller/searcher/component.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 623e5b47d3cc..97849945d85e 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -169,14 +169,14 @@ impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.kind { Kind::FromDatabase { entry, .. } => { - let name = entry.name.from_case(Case::Snake).to_case(Case::Lower); + let entry_name = entry.name.from_case(Case::Snake).to_case(Case::Lower); let self_type_ref = entry.self_type.as_ref(); let self_type_not_here = self_type_ref.filter(|t| *t != &entry.module); if let Some(self_type) = self_type_not_here { let self_name = self_type.name.from_case(Case::Snake).to_case(Case::Title); - write!(f, "{} {}", self_name, name) + write!(f, "{} {}", self_name, entry_name) } else { - write!(f, "{}", name) + write!(f, "{}", entry_name) } } Kind::Virtual { snippet } => write!(f, "{}", snippet.name), From ba1180f256692e7fb8d6196a06690599a189e85e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:23:19 +0200 Subject: [PATCH 084/140] drop unused imports --- app/gui/src/controller/searcher/component/builder.rs | 3 ++- app/gui/src/presenter/searcher/provider.rs | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 9c90ddd2d663..1ec5fafc43b8 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -26,7 +26,6 @@ use crate::model::execution_context; use crate::model::suggestion_database; use double_representation::module; -use double_representation::project; @@ -274,6 +273,8 @@ mod tests { use crate::controller::searcher::component::tests::mock_suggestion_db; + use double_representation::project; + #[derive(Clone, Debug, Eq, PartialEq)] struct ComparableGroupData<'a> { diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index e4f2e3594d1a..4dfa45fab07d 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -4,7 +4,6 @@ use crate::prelude::*; use crate::controller::searcher::action::MatchInfo; use crate::controller::searcher::component; -use crate::model::suggestion_database; use crate::presenter; use enso_text as text; From 01c46febf41c7c4de02268fd62d25b76fcb06e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:28:49 +0200 Subject: [PATCH 085/140] =?UTF-8?q?=C2=A0doc=20and=20rename=20for=20Group:?= =?UTF-8?q?:from=5Fqn=5Fand=5Fsnippets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/gui/src/controller/searcher/component/builder.rs | 2 +- app/gui/src/controller/searcher/component/group.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 1ec5fafc43b8..48c214769513 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -188,7 +188,7 @@ impl List { if let Some(group) = group_with_matching_name { group.insert_entries(&snippets.into_iter().map(Into::into).collect_vec()); } else { - let group = Group::from_qualified_name_and_virtual_components(group_name, snippets); + let group = Group::from_qualified_name_and_snippets(group_name, snippets); favorites_grouping.insert(0, group); } self.grouping_and_order_of_favorites = component::group::List::new(favorites_grouping); diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 608693810b7c..1b3b38496e7a 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -122,7 +122,9 @@ impl Group { Self::from_name_and_project_and_id(name, Some(project_name), Some(component_id)) } - pub fn from_qualified_name_and_virtual_components( + /// Create a group with given name and containing virtual components created from given + /// snippets. + pub fn from_qualified_name_and_snippets( qualified_name: QualifiedName, snippets: impl IntoIterator>, ) -> Self { From c7d85360c2a435ecdf274ccad1c559d5cbdb9220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:31:01 +0200 Subject: [PATCH 086/140] undo one rename --- app/gui/src/controller/searcher/component/builder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 48c214769513..cd0ad9b62623 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -284,11 +284,11 @@ mod tests { } impl<'a> From<&'a component::Group> for ComparableGroupData<'a> { - fn from(group: &'a component::Group) -> Self { + fn from(component: &'a component::Group) -> Self { Self { - name: group.name.as_str(), - component_id: group.component_id, - entries: group.entries.borrow().iter().map(|e| e.id().unwrap()).collect(), + name: component.name.as_str(), + component_id: component.component_id, + entries: component.entries.borrow().iter().map(|e| e.id().unwrap()).collect(), } } } From 13ec19523c0efc40ae36fe0021778d7c4001ea0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:34:24 +0200 Subject: [PATCH 087/140] qn_of_base_lib in tests --- app/gui/src/controller/searcher/component/builder.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index cd0ad9b62623..fbadc466c476 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -468,8 +468,8 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_project = project::QualifiedName::of_standard_base_library(); - let qn_of_group = group::QualifiedName::new(qn_of_base_project, "Group"); + let qn_of_base_lib = project::QualifiedName::of_standard_base_library(); + let qn_of_group = group::QualifiedName::new(qn_of_base_lib, "Group"); let groups = [execution_context::ComponentGroup { project: qn_of_group.project.clone(), name: qn_of_group.name.clone(), @@ -495,8 +495,8 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_project = project::QualifiedName::of_standard_base_library(); - let qn_of_group_1 = group::QualifiedName::new(qn_of_base_project.clone(), "Group 1"); + let qn_of_base_lib = project::QualifiedName::of_standard_base_library(); + let qn_of_group_1 = group::QualifiedName::new(qn_of_base_lib.clone(), "Group 1"); let groups = [execution_context::ComponentGroup { project: qn_of_group_1.project.clone(), name: qn_of_group_1.name.clone(), @@ -506,7 +506,7 @@ mod tests { builder.set_grouping_and_order_of_favorites(&db, &groups); let virtual_component = component::Virtual { name: "Virtual Component", ..default() }; let vc_iter = std::iter::once(Rc::new(virtual_component)); - let qn_of_group_2 = group::QualifiedName::new(qn_of_base_project, "Group 2"); + let qn_of_group_2 = group::QualifiedName::new(qn_of_base_lib, "Group 2"); builder.insert_virtual_components_in_favorites_group(qn_of_group_2.clone(), vc_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); From a5eb3e2960774994538264bb27dc0bab1cbb0515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:38:29 +0200 Subject: [PATCH 088/140] tweak test names and add docs --- app/gui/src/controller/searcher/component/builder.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index fbadc466c476..78de4fe5fe27 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -461,10 +461,12 @@ mod tests { assert_eq!(&entry_names, expected_names); } + /// Test building a component list with a virtual component. The virtual component will be + /// inserted into an existing favorites group. #[test] - fn building_component_list_with_virtual_components_in_existing_favorites_group() { + fn building_component_list_with_virtual_component_in_existing_favorites_group() { use component::group; - let logger = Logger::new("tests::virtual_components_in_existing_favorites_group"); + let logger = Logger::new("tests::virtual_component_in_existing_favorites_group"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); @@ -488,10 +490,12 @@ mod tests { check_names_and_order_of_group_entries(&favorites[0], &expected_entry_names); } + /// Test building a component list with a virtual component. The virtual component will be + /// inserted into a new favorites group. #[test] - fn building_component_list_with_virtual_components_in_new_favorites_group() { + fn building_component_list_with_virtual_component_in_new_favorites_group() { use component::group; - let logger = Logger::new("tests::virtual_components_in_new_favorites_group"); + let logger = Logger::new("tests::virtual_component_in_new_favorites_group"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); From 81c9b3f62a237ec8e7690bc09aed011e55086ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:41:11 +0200 Subject: [PATCH 089/140] doc for group::QualifiedName --- app/gui/src/controller/searcher/component/group.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 1b3b38496e7a..011628505483 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -19,9 +19,12 @@ use std::cmp; // === QualifiedName === // ===================== +/// Fully qualified name of a component group. #[derive(Clone, Debug, PartialEq, Eq)] pub struct QualifiedName { + /// Fully qualified name of the project containing the definition of the group. pub project: project::QualifiedName, + /// The name of the group in the scope of the project where it was defined. pub name: ImString, } From a69aa900a9144998c952910e5da449072fbc9cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:45:13 +0200 Subject: [PATCH 090/140] tweak doc of from_name_and_project_and_id --- app/gui/src/controller/searcher/component/group.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 011628505483..fc5e807064d1 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -103,7 +103,8 @@ impl Deref for Group { } impl Group { - /// Create a named empty group referring to module with specified component ID. + /// Create a named empty group referring to module with specified component ID and in the given + /// project. pub fn from_name_and_project_and_id( name: impl Into, project: Option, From 9497cd5d374a9f2953c5b0fe1075be1d18917658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 15:47:43 +0200 Subject: [PATCH 091/140] doc for insert_entries --- app/gui/src/controller/searcher/component/group.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index fc5e807064d1..3c1ad1c69b10 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -174,6 +174,7 @@ impl Group { }) } + /// Insert given entries as first entries in the group. pub fn insert_entries(&mut self, entries: &[Component]) { let group_data = Rc::make_mut(&mut self.data); group_data.entries.borrow_mut().splice(0..0, entries.iter().cloned()); From 1d07b5b3430e1817a5d763c92483fd0433054e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 16:57:23 +0200 Subject: [PATCH 092/140] parse docs --- Cargo.lock | 1 - app/gui/Cargo.toml | 1 - app/gui/src/controller/searcher.rs | 57 ++++++++----------- app/gui/src/controller/searcher/action.rs | 9 +-- .../controller/searcher/action/hardcoded.rs | 2 +- 5 files changed, 30 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae0070db8f75..d67b0d9f542e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1960,7 +1960,6 @@ dependencies = [ "ast", "bimap", "console_error_panic_hook", - "const_format", "convert_case 0.5.0", "double-representation", "engine-protocol", diff --git a/app/gui/Cargo.toml b/app/gui/Cargo.toml index a1ce7d25937c..0b40465b420c 100644 --- a/app/gui/Cargo.toml +++ b/app/gui/Cargo.toml @@ -38,7 +38,6 @@ parser = { path = "language/parser" } span-tree = { path = "language/span-tree" } bimap = { version = "0.4.0" } console_error_panic_hook = { version = "0.1.6" } -const_format = { version = "0.2.22" } convert_case = { version = "0.5.0" } failure = { version = "0.1.6" } flo_stream = { version = "0.4.0" } diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 03d01cd8c5a5..496797fd577c 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -13,7 +13,6 @@ use crate::model::suggestion_database; use crate::model::suggestion_database::entry::CodeToInsert; use crate::notification; -use const_format::concatcp; use double_representation::graph::GraphInfo; use double_representation::graph::LocationHint; use double_representation::module::QualifiedName; @@ -54,18 +53,6 @@ const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; /// components. const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; -macro_rules! html_docs_with_summary_and_synopsis { - ($summary_html:literal, $synopsis_html:literal) => { - concatcp!( - "

", - $summary_html, - "

", - $synopsis_html, - "
" - ) - }; -} - thread_local! { /// Code snippets of default literal values of text and number type. The snippets are /// documented as code that can be used as input nodes. When converted to [`Component`]s and @@ -75,23 +62,23 @@ thread_local! { name: "text input", code: "\"\"", return_type: "Standard.Base.Data.Text.Text", - documentation_html: html_docs_with_summary_and_synopsis!( - "A text input node.", - "An empty text. The value can be edited and used as an input for other nodes." - ), + documentation: + "A text input node.\n\n\ + An empty text. The value can be edited and used as an input for other nodes." + , icon: ide_view_component_group::icon::Id::TextInput, }, LiteralSnippet { name: "number input", code: "0", return_type: "Standard.Base.Data.Numbers.Number", - documentation_html: html_docs_with_summary_and_synopsis!( - "A number input node.", - "A zero number. The value can be edited and used as an input for other nodes." - ), + documentation: + "A number input node.\n\n\ + A zero number. The value can be edited and used as an input for other nodes." + , icon: ide_view_component_group::icon::Id::NumberInput, }, - ].into_iter().map(|c| Rc::new(c.into())).collect_vec(); + ].into_iter().map(|c| Rc::new(c.try_into().unwrap())).collect_vec(); } @@ -102,26 +89,30 @@ thread_local! { /// A snippet of code with a literal value, with description and syntax metadata. struct LiteralSnippet { - pub name: &'static str, - pub code: &'static str, - pub return_type: &'static str, - pub documentation_html: &'static str, - pub icon: ide_view_component_group::icon::Id, + pub name: &'static str, + pub code: &'static str, + pub return_type: &'static str, + pub documentation: &'static str, + pub icon: ide_view_component_group::icon::Id, } -impl From for component::HardcodedSnippet { - fn from(literal: LiteralSnippet) -> component::HardcodedSnippet { - component::HardcodedSnippet { +impl TryFrom for component::HardcodedSnippet { + type Error = failure::Error; + fn try_from(literal: LiteralSnippet) -> Result { + let doc_parser = parser::DocParser::new()?; + let doc_string = literal.documentation.to_string(); + let documentation_html = doc_parser.generate_html_doc_pure(doc_string)?; + Ok(component::HardcodedSnippet { name: literal.name, code: literal.code, this_arg: None, argument_types: vec![], - return_type: Some(literal.return_type.try_into().unwrap()), + return_type: Some(literal.return_type.try_into()?), imports: vec![], - documentation_html: Some(literal.documentation_html), + documentation_html: Some(documentation_html), method_id: None, icon: literal.icon.as_str().into(), - } + }) } } diff --git a/app/gui/src/controller/searcher/action.rs b/app/gui/src/controller/searcher/action.rs index 1febc85483e1..38a2c23b4be2 100644 --- a/app/gui/src/controller/searcher/action.rs +++ b/app/gui/src/controller/searcher/action.rs @@ -57,10 +57,11 @@ impl Suggestion { /// Return the documentation assigned to the suggestion. pub fn documentation_html(&self) -> Option<&str> { - match self { - Suggestion::FromDatabase(s) => s.documentation_html.as_ref().map(AsRef::::as_ref), - Suggestion::Hardcoded(s) => s.documentation_html, - } + let doc_html = match self { + Suggestion::FromDatabase(s) => &s.documentation_html, + Suggestion::Hardcoded(s) => &s.documentation_html, + }; + doc_html.as_ref().map(AsRef::::as_ref) } /// The Id of the method called by a suggestion, or [`None`] if the suggestion is not a method diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index d6a2b881f3f9..5c31b5dc64dd 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -102,7 +102,7 @@ pub struct Suggestion { /// An import required by the suggestion. pub imports: Vec, /// The documentation bound to the suggestion. - pub documentation_html: Option<&'static str>, + pub documentation_html: Option, /// The id of the method called by the suggestion. pub method_id: Option, /// The name of the icon bound to this entry. From 61b9be37b860c8c3721a72274d74fcc442b24099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 16:57:49 +0200 Subject: [PATCH 093/140] cargo fmt --- app/gui/src/controller/searcher.rs | 2 +- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/presenter/searcher.rs | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 496797fd577c..9f71453ed0d9 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -72,7 +72,7 @@ thread_local! { name: "number input", code: "0", return_type: "Standard.Base.Data.Numbers.Number", - documentation: + documentation: "A number input node.\n\n\ A zero number. The value can be edited and used as an input for other nodes." , diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 97849945d85e..81b135b5b954 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -66,7 +66,7 @@ pub enum Kind { /// A component from the [`suggestion_database`]. FromDatabase { /// The ID of the component in the [`suggestion_database`]. - id: Immutable, + id: Immutable, /// The component's entry in the [`suggestion_database`]. entry: Rc, }, diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index 5b6f2027392a..ed7a928b24b4 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -138,8 +138,7 @@ impl Model { let suggestion = match component.kind { component::Kind::FromDatabase { entry, .. } => Suggestion::FromDatabase(entry.clone_ref()), - component::Kind::Virtual { snippet } => - Suggestion::Hardcoded(snippet.clone_ref()), + component::Kind::Virtual { snippet } => Suggestion::Hardcoded(snippet.clone_ref()), }; self.controller.use_suggestion(suggestion) }); @@ -211,7 +210,9 @@ impl Model { component::Kind::FromDatabase { entry, .. } => { if let Some(documentation) = &entry.documentation_html { let title = title_for_docs(&entry); - format!("

{title}

{documentation}") + format!( + "

{title}

{documentation}" + ) } else { doc_placeholder_for(&entry) } From 840c620a955e63c8ce0eeb1597f4610e90ff2577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 17:20:17 +0200 Subject: [PATCH 094/140] fix tests --- .../src/controller/searcher/component/builder.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 78de4fe5fe27..38903cc03002 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -479,14 +479,14 @@ mod tests { components: vec![qn_of_db_entry_0.clone()], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); - let virtual_component = component::Virtual { name: "Virtual Component", ..default() }; - let vc_iter = std::iter::once(Rc::new(virtual_component)); - builder.insert_virtual_components_in_favorites_group(qn_of_group.clone(), vc_iter); + let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; + let snippet_iter = std::iter::once(Rc::new(snippet)); + builder.insert_virtual_components_in_favorites_group(qn_of_group.clone(), snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; assert_eq!(favorites.len(), 1, "Expected one group of favorites, got: {:?}.", favorites); - let expected_entry_names = ["Virtual Component", "TopModule1"]; + let expected_entry_names = ["test snippet", "TopModule1"]; check_names_and_order_of_group_entries(&favorites[0], &expected_entry_names); } @@ -508,17 +508,17 @@ mod tests { components: vec![qn_of_db_entry_0.clone()], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); - let virtual_component = component::Virtual { name: "Virtual Component", ..default() }; - let vc_iter = std::iter::once(Rc::new(virtual_component)); + let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; + let snippet_iter = std::iter::once(Rc::new(snippet)); let qn_of_group_2 = group::QualifiedName::new(qn_of_base_lib, "Group 2"); - builder.insert_virtual_components_in_favorites_group(qn_of_group_2.clone(), vc_iter); + builder.insert_virtual_components_in_favorites_group(qn_of_group_2.clone(), snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; assert_eq!(favorites.len(), 2, "Expected two groups of favorites, got: {:?}.", favorites); let group_at_0 = &favorites[0]; assert_eq!(group_at_0.name, "Group 2"); - check_names_and_order_of_group_entries(group_at_0, &["Virtual Component"]); + check_names_and_order_of_group_entries(group_at_0, &["test snippet"]); let group_at_1 = &favorites[1]; assert_eq!(group_at_1.name, "Group 1"); check_names_and_order_of_group_entries(group_at_1, &["TopModule1"]); From 26a77a140fe42095b9cfdb81ea5e1145ae52e4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:17:55 +0200 Subject: [PATCH 095/140] add_comp_from_db_to_grps_by_parent_mod --- .../controller/searcher/component/builder.rs | 66 ++++++++++++------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 38903cc03002..baa686e5c6c6 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -107,6 +107,47 @@ impl List { Self { local_scope, ..self } } + /// Add a component with given id and entry to component groups based on its parent module. + /// Return `true` if added to any component group. + /// + /// The component will be considered for adding to the following groups: + /// - the [`ModuleGroup`] of the entry's parent module, if found; + /// - the [`List::local_scope`], if the entry's parent module is the local scope; + /// - the group containing the flattened content of the entry's top module, if found. + #[must_use] + fn add_component_from_db_to_groups_by_parent_module(&mut self, + db: &model::SuggestionDatabase, + id: component::Id, + entry: &Rc, + ) -> bool { + use suggestion_database::entry::Kind; + entry.parent_module().map_or(false, |parent_module| { + let mut component_pushed_somewhere = false; + let mut push_component_to_group_and_set_pushed = |group: &component::Group| { + group.entries.borrow_mut().push(Component::new_from_db(id, entry.clone_ref())); + component_pushed_somewhere = true; + }; + if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { + push_component_to_group_and_set_pushed(&parent_group.content); + let parent_id = parent_group.content.component_id; + let local_scope_id = self.local_scope.component_id; + let in_local_scope = + parent_id == local_scope_id && local_scope_id.is_some(); + let not_module = entry.kind != Kind::Module; + if in_local_scope && not_module { + push_component_to_group_and_set_pushed(&self.local_scope); + } + } + let top_module = parent_module.top_module(); + if let Some(top_group) = self.lookup_module_group(db, &top_module) { + if let Some(flatten_group) = &mut top_group.flattened_content { + push_component_to_group_and_set_pushed(&flatten_group); + } + } + component_pushed_somewhere + }) + } + /// Extend the list with new entries looked up by ID in suggestion database. Allow those /// entries to be present in [`component::List::favorites`]. See the module documentation for /// more details. @@ -115,35 +156,12 @@ impl List { db: &model::SuggestionDatabase, entries: impl IntoIterator, ) { - use suggestion_database::entry::Kind; - let local_scope_id = self.local_scope.component_id; let lookup_component_by_id = |id| Some(Component::new_from_db(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { if let component::Kind::FromDatabase { id, ref entry } = component.kind { self.allowed_favorites.insert(*id); - let mut component_inserted_somewhere = false; - if let Some(parent_module) = entry.parent_module() { - if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { - parent_group.content.entries.borrow_mut().push(component.clone_ref()); - component_inserted_somewhere = true; - let parent_id = parent_group.content.component_id; - let in_local_scope = - parent_id == local_scope_id && local_scope_id.is_some(); - let not_module = entry.kind != Kind::Module; - if in_local_scope && not_module { - self.local_scope.entries.borrow_mut().push(component.clone_ref()); - } - } - let top_module = parent_module.top_module(); - if let Some(top_group) = self.lookup_module_group(db, &top_module) { - if let Some(flatten_group) = &mut top_group.flattened_content { - flatten_group.entries.borrow_mut().push(component.clone_ref()); - component_inserted_somewhere = true; - } - } - } - if component_inserted_somewhere { + if self.add_component_from_db_to_groups_by_parent_module(db, *id, entry) { self.all_components.push(component); } } else { From e78010d601eb8218b229e36afdd083aceebbe145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:21:26 +0200 Subject: [PATCH 096/140] doc for qn() --- app/gui/src/controller/searcher/component/group.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 3c1ad1c69b10..791aa13f23ec 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -242,6 +242,7 @@ impl Group { } } + /// The fully qualified name of the components group, or [`None`] if not available. pub fn qualified_name(&self) -> Option { let name = self.name.clone(); self.project.as_ref().map(|p| QualifiedName { project: p.clone(), name }) From 471a88ffd6e40d2c1d225590bb2e324384ffbee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:25:55 +0200 Subject: [PATCH 097/140] del empty line --- app/gui/src/model/execution_context.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/app/gui/src/model/execution_context.rs b/app/gui/src/model/execution_context.rs index cb4aa2d89e72..e437bd21ee46 100644 --- a/app/gui/src/model/execution_context.rs +++ b/app/gui/src/model/execution_context.rs @@ -313,7 +313,6 @@ impl ComponentGroup { impl TryFrom for ComponentGroup { type Error = failure::Error; - fn try_from(group: language_server::LibraryComponentGroup) -> FallibleResult { Self::from_language_server_protocol_struct(group) } From ab09fa11bb8150f7593f56c9fa9d6a67bda34ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:33:08 +0200 Subject: [PATCH 098/140] tweak error for parsed_icon for VirtualComponent --- app/gui/src/presenter/searcher/provider.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index 4dfa45fab07d..135c3cad7014 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -197,7 +197,12 @@ impl list_view::entry::ModelProvider for Component let icon = &snippet.icon; let parsed_icon = component_group_view::icon::Id::from_str(icon); parsed_icon.unwrap_or_else(|_| { - event!(ERROR, "Virtual component uses an icon name {icon} not found among predefined icons."); + let msg = iformat!( + "A virtual component named " snippet.name;? + " uses an icon name " icon + " which is not found among predefined icons. A default icon will be used." + ); + event!(ERROR, "{msg}"); default() }) } From 7a6e6ad5c8ddd2628996278640aea8d6a564c37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:37:29 +0200 Subject: [PATCH 099/140] doc for as_str --- .../component-browser/component-group/src/icon/define_macro.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/app/gui/view/component-browser/component-group/src/icon/define_macro.rs b/app/gui/view/component-browser/component-group/src/icon/define_macro.rs index ad325ba8d11c..a7ddc52a28e5 100644 --- a/app/gui/view/component-browser/component-group/src/icon/define_macro.rs +++ b/app/gui/view/component-browser/component-group/src/icon/define_macro.rs @@ -99,6 +99,7 @@ macro_rules! define_icons { $(f(Self::$variant);)* } + /// Get a string identifier with the icon's name. pub fn as_str(&self) -> &'static str { match self { $(Self::$variant => stringify!($variant),)* From 2710109e4b1d68fa84c3bb48ab8b2e07046ac726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:39:44 +0200 Subject: [PATCH 100/140] cargo fmt --- app/gui/src/controller/searcher/component/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index baa686e5c6c6..58ce35410ea1 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -115,7 +115,8 @@ impl List { /// - the [`List::local_scope`], if the entry's parent module is the local scope; /// - the group containing the flattened content of the entry's top module, if found. #[must_use] - fn add_component_from_db_to_groups_by_parent_module(&mut self, + fn add_component_from_db_to_groups_by_parent_module( + &mut self, db: &model::SuggestionDatabase, id: component::Id, entry: &Rc, @@ -131,8 +132,7 @@ impl List { push_component_to_group_and_set_pushed(&parent_group.content); let parent_id = parent_group.content.component_id; let local_scope_id = self.local_scope.component_id; - let in_local_scope = - parent_id == local_scope_id && local_scope_id.is_some(); + let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); let not_module = entry.kind != Kind::Module; if in_local_scope && not_module { push_component_to_group_and_set_pushed(&self.local_scope); From d02cb07ac0325a9d7666f7172bf4435a6820776e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 18:46:28 +0200 Subject: [PATCH 101/140] fix clippy --- app/gui/src/controller/searcher/component/builder.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 58ce35410ea1..2905fe25c803 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -141,7 +141,7 @@ impl List { let top_module = parent_module.top_module(); if let Some(top_group) = self.lookup_module_group(db, &top_module) { if let Some(flatten_group) = &mut top_group.flattened_content { - push_component_to_group_and_set_pushed(&flatten_group); + push_component_to_group_and_set_pushed(flatten_group); } } component_pushed_somewhere @@ -494,12 +494,12 @@ mod tests { project: qn_of_group.project.clone(), name: qn_of_group.name.clone(), color: None, - components: vec![qn_of_db_entry_0.clone()], + components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); - builder.insert_virtual_components_in_favorites_group(qn_of_group.clone(), snippet_iter); + builder.insert_virtual_components_in_favorites_group(qn_of_group, snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; @@ -521,15 +521,15 @@ mod tests { let qn_of_group_1 = group::QualifiedName::new(qn_of_base_lib.clone(), "Group 1"); let groups = [execution_context::ComponentGroup { project: qn_of_group_1.project.clone(), - name: qn_of_group_1.name.clone(), + name: qn_of_group_1.name, color: None, - components: vec![qn_of_db_entry_0.clone()], + components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); let qn_of_group_2 = group::QualifiedName::new(qn_of_base_lib, "Group 2"); - builder.insert_virtual_components_in_favorites_group(qn_of_group_2.clone(), snippet_iter); + builder.insert_virtual_components_in_favorites_group(qn_of_group_2, snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; From d103e49dba48e73a4386c8448b148650f32d6bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 19:02:28 +0200 Subject: [PATCH 102/140] bump wasm size limit --- build-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-config.yaml b/build-config.yaml index 2d5d4dc8611b..34112d51ab6a 100644 --- a/build-config.yaml +++ b/build-config.yaml @@ -1,6 +1,6 @@ # Options intended to be common for all developers. -wasm-size-limit: 5.23 MiB +wasm-size-limit: 5.24 MiB required-versions: cargo-watch: ^8.1.1 From 54afe55e69acdc5f97e8c4a69db9ece0159f7ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 19:10:17 +0200 Subject: [PATCH 103/140] Revert "add_comp_from_db_to_grps_by_parent_mod" This reverts commit 26a77a140fe42095b9cfdb81ea5e1145ae52e4cc. --- .../controller/searcher/component/builder.rs | 66 +++++++------------ 1 file changed, 24 insertions(+), 42 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 2905fe25c803..7d886b280732 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -107,47 +107,6 @@ impl List { Self { local_scope, ..self } } - /// Add a component with given id and entry to component groups based on its parent module. - /// Return `true` if added to any component group. - /// - /// The component will be considered for adding to the following groups: - /// - the [`ModuleGroup`] of the entry's parent module, if found; - /// - the [`List::local_scope`], if the entry's parent module is the local scope; - /// - the group containing the flattened content of the entry's top module, if found. - #[must_use] - fn add_component_from_db_to_groups_by_parent_module( - &mut self, - db: &model::SuggestionDatabase, - id: component::Id, - entry: &Rc, - ) -> bool { - use suggestion_database::entry::Kind; - entry.parent_module().map_or(false, |parent_module| { - let mut component_pushed_somewhere = false; - let mut push_component_to_group_and_set_pushed = |group: &component::Group| { - group.entries.borrow_mut().push(Component::new_from_db(id, entry.clone_ref())); - component_pushed_somewhere = true; - }; - if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { - push_component_to_group_and_set_pushed(&parent_group.content); - let parent_id = parent_group.content.component_id; - let local_scope_id = self.local_scope.component_id; - let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); - let not_module = entry.kind != Kind::Module; - if in_local_scope && not_module { - push_component_to_group_and_set_pushed(&self.local_scope); - } - } - let top_module = parent_module.top_module(); - if let Some(top_group) = self.lookup_module_group(db, &top_module) { - if let Some(flatten_group) = &mut top_group.flattened_content { - push_component_to_group_and_set_pushed(flatten_group); - } - } - component_pushed_somewhere - }) - } - /// Extend the list with new entries looked up by ID in suggestion database. Allow those /// entries to be present in [`component::List::favorites`]. See the module documentation for /// more details. @@ -156,12 +115,35 @@ impl List { db: &model::SuggestionDatabase, entries: impl IntoIterator, ) { + use suggestion_database::entry::Kind; + let local_scope_id = self.local_scope.component_id; let lookup_component_by_id = |id| Some(Component::new_from_db(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { if let component::Kind::FromDatabase { id, ref entry } = component.kind { self.allowed_favorites.insert(*id); - if self.add_component_from_db_to_groups_by_parent_module(db, *id, entry) { + let mut component_inserted_somewhere = false; + if let Some(parent_module) = entry.parent_module() { + if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { + parent_group.content.entries.borrow_mut().push(component.clone_ref()); + component_inserted_somewhere = true; + let parent_id = parent_group.content.component_id; + let in_local_scope = + parent_id == local_scope_id && local_scope_id.is_some(); + let not_module = entry.kind != Kind::Module; + if in_local_scope && not_module { + self.local_scope.entries.borrow_mut().push(component.clone_ref()); + } + } + let top_module = parent_module.top_module(); + if let Some(top_group) = self.lookup_module_group(db, &top_module) { + if let Some(flatten_group) = &mut top_group.flattened_content { + flatten_group.entries.borrow_mut().push(component.clone_ref()); + component_inserted_somewhere = true; + } + } + } + if component_inserted_somewhere { self.all_components.push(component); } } else { From 39287ab6009e79c0df7a71754b6da02d45606c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Mon, 8 Aug 2022 19:30:27 +0200 Subject: [PATCH 104/140] new_from_database_entry --- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/controller/searcher/component/builder.rs | 3 ++- app/gui/src/controller/searcher/component/group.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 81b135b5b954..b1476372362b 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -102,7 +102,7 @@ impl Component { /// Construct a new component from a [`suggestion_database`] entry. /// /// The matching info will be filled for an empty pattern. - pub fn new_from_db(id: Id, entry: Rc) -> Self { + pub fn new_from_database_entry(id: Id, entry: Rc) -> Self { let kind = Kind::FromDatabase { id: Immutable(id), entry }; Self { kind, match_info: default() } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 7d886b280732..41f9c5f3557e 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -117,7 +117,8 @@ impl List { ) { use suggestion_database::entry::Kind; let local_scope_id = self.local_scope.component_id; - let lookup_component_by_id = |id| Some(Component::new_from_db(id, db.lookup(id).ok()?)); + let lookup_component_by_id = + |id| Some(Component::new_from_database_entry(id, db.lookup(id).ok()?)); let components = entries.into_iter().filter_map(lookup_component_by_id); for component in components { if let component::Kind::FromDatabase { id, ref entry } = component.kind { diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 791aa13f23ec..b20b9eb4b43f 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -155,7 +155,7 @@ impl Group { ) -> Option { let lookup_component = |qualified_name| { let (id, suggestion) = suggestion_db.lookup_by_qualified_name(qualified_name)?; - Some(Component::new_from_db(id, suggestion)) + Some(Component::new_from_database_entry(id, suggestion)) }; let components = &group.components; let looked_up_components = components.iter().filter_map(lookup_component).collect_vec(); From 00463087089bb118a5ed7abdf43658c75ca5b364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 10:35:13 +0200 Subject: [PATCH 105/140] fix for wasm test --- app/gui/src/controller/searcher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 9f71453ed0d9..2d2dd1866345 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1859,7 +1859,7 @@ pub mod test { // Prepare a sample component group to be returned by a mock Language Server client. let module_qualified_name = crate::test::mock::data::module_qualified_name().to_string(); let sample_ls_component_group = language_server::LibraryComponentGroup { - library: "".to_string(), + library: project::QualifiedName::of_standard_base_library().to_string(), name: "Test Group 1".to_string(), color: None, icon: None, From 889ded422face68a449517d7eeab7ae828a72581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 10:48:48 +0200 Subject: [PATCH 106/140] continue fixing wasm test --- app/gui/src/controller/searcher.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 2d2dd1866345..9b0d01aabe24 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1897,10 +1897,12 @@ pub mod test { ipanic!("Wrong top modules in Component List: {components.top_modules():?}"); } let favorites = &components.favorites; - assert_eq!(favorites.len(), 1); - let favorites_group = &favorites[0]; - assert_eq!(favorites_group.name, "Test Group 1"); - let favorites_entries = favorites_group.entries.borrow(); + assert_eq!(favorites.len(), 2); + let favorites_group_0 = &favorites[0]; + assert_eq!(favorites_group_0.name, INPUT_COMPONENT_GROUP_NAME); + let favorites_group_1 = &favorites[1]; + assert_eq!(favorites_group_1.name, "Test Group 1"); + let favorites_entries = favorites_group_1.entries.borrow(); assert_eq!(favorites_entries.len(), 1); assert_eq!(favorites_entries[0].id().unwrap(), 1); } From 37d7b9831a0e7019d46cffce4b94a60ed5138c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 14:31:18 +0200 Subject: [PATCH 107/140] review: drop prefix "of_" in func name --- app/gui/controller/double-representation/src/project.rs | 4 ++-- app/gui/src/controller/searcher.rs | 4 ++-- app/gui/src/controller/searcher/component.rs | 2 +- app/gui/src/controller/searcher/component/builder.rs | 8 ++++---- app/gui/src/controller/searcher/component/group.rs | 4 ++-- app/gui/src/model/execution_context/synchronized.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index bfbc6d769eac..601ef873c81b 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -77,7 +77,7 @@ impl QualifiedName { } /// Return the qualified name of the "Standard.Base" library project. - pub fn of_standard_base_library() -> Self { + pub fn standard_base_library() -> Self { Self::from_segments("Standard", "Base").unwrap() } @@ -160,6 +160,6 @@ mod test { #[test] fn qualified_name_of_standard_base_library_does_not_panic() { - let _ = QualifiedName::of_standard_base_library(); + let _ = QualifiedName::standard_base_library(); } } diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 9b0d01aabe24..cb02d17ace96 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1256,7 +1256,7 @@ fn component_list_builder_with_favorites<'a>( builder = builder.with_local_scope_module_id(id); } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); - let base_lib_qn = project::QualifiedName::of_standard_base_library(); + let base_lib_qn = project::QualifiedName::standard_base_library(); let input_group_name = INPUT_COMPONENT_GROUP_NAME; let input_group_qn = component::group::QualifiedName::new(base_lib_qn, input_group_name); let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|c| c.clone()); @@ -1859,7 +1859,7 @@ pub mod test { // Prepare a sample component group to be returned by a mock Language Server client. let module_qualified_name = crate::test::mock::data::module_qualified_name().to_string(); let sample_ls_component_group = language_server::LibraryComponentGroup { - library: project::QualifiedName::of_standard_base_library().to_string(), + library: project::QualifiedName::standard_base_library().to_string(), name: "Test Group 1".to_string(), color: None, icon: None, diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index b1476372362b..8d74996f3699 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -366,7 +366,7 @@ pub(crate) mod tests { ) -> Vec { let db_entries = component_ids.iter().map(|id| db.lookup(*id).unwrap()); let group = crate::model::execution_context::ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Test Group 1".into(), color: None, components: db_entries.into_iter().map(|e| e.qualified_name()).collect(), diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 41f9c5f3557e..a58f3d032481 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -412,7 +412,7 @@ mod tests { assert_eq!(db.lookup_by_qualified_name_str(QN_NOT_IN_DB), None); let groups = [ execution_context::ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Group 1".into(), color: None, components: vec![ @@ -426,7 +426,7 @@ mod tests { ], }, execution_context::ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Group 2".into(), color: None, components: vec![ @@ -471,7 +471,7 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_lib = project::QualifiedName::of_standard_base_library(); + let qn_of_base_lib = project::QualifiedName::standard_base_library(); let qn_of_group = group::QualifiedName::new(qn_of_base_lib, "Group"); let groups = [execution_context::ComponentGroup { project: qn_of_group.project.clone(), @@ -500,7 +500,7 @@ mod tests { let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_lib = project::QualifiedName::of_standard_base_library(); + let qn_of_base_lib = project::QualifiedName::standard_base_library(); let qn_of_group_1 = group::QualifiedName::new(qn_of_base_lib.clone(), "Group 1"); let groups = [execution_context::ComponentGroup { project: qn_of_group_1.project.clone(), diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index b20b9eb4b43f..8f2fcb670f6b 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -367,7 +367,7 @@ mod tests { // order. Some of the names correspond to entries present in the suggestion database, // some do not. let ec_group = execution_context::ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Test Group 1".into(), color: color::Rgb::from_css_hex("#aabbcc"), components: vec![ @@ -401,7 +401,7 @@ mod tests { let logger = Logger::new("tests::constructing_component_group_from_names_not_found_in_db"); let suggestion_db = Rc::new(mock_suggestion_db(logger)); let ec_group = execution_context::ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Input".into(), color: None, components: vec!["NAME.NOT.FOUND.IN.DB".into()], diff --git a/app/gui/src/model/execution_context/synchronized.rs b/app/gui/src/model/execution_context/synchronized.rs index 6f9925ac224c..de4569843aa2 100644 --- a/app/gui/src/model/execution_context/synchronized.rs +++ b/app/gui/src/model/execution_context/synchronized.rs @@ -619,7 +619,7 @@ pub mod test { // Verify that the second component group was parsed and has expected contents. assert_eq!(groups[1], ComponentGroup { - project: project::QualifiedName::of_standard_base_library(), + project: project::QualifiedName::standard_base_library(), name: "Input".into(), color: None, components: vec!["Standard.Base.System.File.new".into(),], From 143385c163056b24206f97a8a5edd733f8e1c467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 15:59:59 +0200 Subject: [PATCH 108/140] review: remove dead code --- .../controller/searcher/component/builder.rs | 59 ++++++++----------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index a58f3d032481..dcaad64c2ed0 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -113,46 +113,37 @@ impl List { pub fn extend_list_and_allow_favorites_with_ids( &mut self, db: &model::SuggestionDatabase, - entries: impl IntoIterator, + entry_ids: impl IntoIterator, ) { use suggestion_database::entry::Kind; let local_scope_id = self.local_scope.component_id; - let lookup_component_by_id = - |id| Some(Component::new_from_database_entry(id, db.lookup(id).ok()?)); - let components = entries.into_iter().filter_map(lookup_component_by_id); - for component in components { - if let component::Kind::FromDatabase { id, ref entry } = component.kind { - self.allowed_favorites.insert(*id); - let mut component_inserted_somewhere = false; - if let Some(parent_module) = entry.parent_module() { - if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { - parent_group.content.entries.borrow_mut().push(component.clone_ref()); - component_inserted_somewhere = true; - let parent_id = parent_group.content.component_id; - let in_local_scope = - parent_id == local_scope_id && local_scope_id.is_some(); - let not_module = entry.kind != Kind::Module; - if in_local_scope && not_module { - self.local_scope.entries.borrow_mut().push(component.clone_ref()); - } - } - let top_module = parent_module.top_module(); - if let Some(top_group) = self.lookup_module_group(db, &top_module) { - if let Some(flatten_group) = &mut top_group.flattened_content { - flatten_group.entries.borrow_mut().push(component.clone_ref()); - component_inserted_somewhere = true; - } + let id_and_looked_up_entry = |id| Some((id, db.lookup(id).ok()?)); + let ids_and_entries = entry_ids.into_iter().filter_map(id_and_looked_up_entry); + for (id, entry) in ids_and_entries { + self.allowed_favorites.insert(id); + let component = Component::new_from_database_entry(id, entry.clone_ref()); + let mut component_inserted_somewhere = false; + if let Some(parent_module) = entry.parent_module() { + if let Some(parent_group) = self.lookup_module_group(db, &parent_module) { + parent_group.content.entries.borrow_mut().push(component.clone_ref()); + component_inserted_somewhere = true; + let parent_id = parent_group.content.component_id; + let in_local_scope = parent_id == local_scope_id && local_scope_id.is_some(); + let not_module = entry.kind != Kind::Module; + if in_local_scope && not_module { + self.local_scope.entries.borrow_mut().push(component.clone_ref()); } } - if component_inserted_somewhere { - self.all_components.push(component); + let top_module = parent_module.top_module(); + if let Some(top_group) = self.lookup_module_group(db, &top_module) { + if let Some(flatten_group) = &mut top_group.flattened_content { + flatten_group.entries.borrow_mut().push(component.clone_ref()); + component_inserted_somewhere = true; + } } - } else { - let msg = iformat!( - "The suggestion database returned a component of a non-FromDatabase kind: " - component;? - ); - event!(ERROR, "{msg}"); + } + if component_inserted_somewhere { + self.all_components.push(component); } } } From f9fe2db95091c7a3f5e9a88dd981cb5c61eee760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 16:01:49 +0200 Subject: [PATCH 109/140] revert unnecessary line split --- app/gui/src/controller/searcher/component/builder.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index dcaad64c2ed0..8adb8cda387a 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -134,8 +134,7 @@ impl List { self.local_scope.entries.borrow_mut().push(component.clone_ref()); } } - let top_module = parent_module.top_module(); - if let Some(top_group) = self.lookup_module_group(db, &top_module) { + if let Some(top_group) = self.lookup_module_group(db, &parent_module.top_module()) { if let Some(flatten_group) = &mut top_group.flattened_content { flatten_group.entries.borrow_mut().push(component.clone_ref()); component_inserted_somewhere = true; From e7da4b2f8ac5e3359d761e1db18b384ab8d93132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 16:42:32 +0200 Subject: [PATCH 110/140] review: rename closure argument --- app/gui/src/controller/searcher.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index cb02d17ace96..a147e4771df2 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1259,7 +1259,7 @@ fn component_list_builder_with_favorites<'a>( let base_lib_qn = project::QualifiedName::standard_base_library(); let input_group_name = INPUT_COMPONENT_GROUP_NAME; let input_group_qn = component::group::QualifiedName::new(base_lib_qn, input_group_name); - let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|c| c.clone()); + let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|snippet| snippet.clone()); builder.insert_virtual_components_in_favorites_group(input_group_qn, snippets); builder } From 348abd5f60158fd648ff23d524f2e6ab49f11349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 16:42:45 +0200 Subject: [PATCH 111/140] review: delete group::QualifiedName struct --- app/gui/src/controller/searcher.rs | 3 +- .../controller/searcher/component/builder.rs | 41 ++++++++++--------- .../controller/searcher/component/group.rs | 37 +++-------------- 3 files changed, 27 insertions(+), 54 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index a147e4771df2..7b3d601202a5 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1258,9 +1258,8 @@ fn component_list_builder_with_favorites<'a>( builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let base_lib_qn = project::QualifiedName::standard_base_library(); let input_group_name = INPUT_COMPONENT_GROUP_NAME; - let input_group_qn = component::group::QualifiedName::new(base_lib_qn, input_group_name); let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|snippet| snippet.clone()); - builder.insert_virtual_components_in_favorites_group(input_group_qn, snippets); + builder.insert_virtual_components_in_favorites_group(input_group_name, base_lib_qn, snippets); builder } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index 8adb8cda387a..f04b11d895b4 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -26,6 +26,7 @@ use crate::model::execution_context; use crate::model::suggestion_database; use double_representation::module; +use double_representation::project; @@ -164,22 +165,24 @@ impl List { std::mem::take(&mut self.grouping_and_order_of_favorites).into_iter().collect_vec() } - /// Insert virtual components at the beginning of a favorites group with given name. If a group - /// with that name does not exist, it is created. The virtual components are created from the - /// given snippets. + /// Insert virtual components at the beginning of a favorites group with given name defined in + /// given project. If a group with that name and project does not exist, it is created. The + /// virtual components are created from the given snippets. pub fn insert_virtual_components_in_favorites_group( &mut self, - group_name: component::group::QualifiedName, + group_name: &str, + project: project::QualifiedName, snippets: impl IntoIterator>, ) { use component::Group; let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); - let name_match = |g: &&mut Group| g.qualified_name().as_ref() == Some(&group_name); - let group_with_matching_name = favorites_grouping.iter_mut().find(name_match); + let name_and_project_match = + |g: &&mut Group| g.name == group_name && g.project.as_ref() == Some(&project); + let group_with_matching_name = favorites_grouping.iter_mut().find(name_and_project_match); if let Some(group) = group_with_matching_name { group.insert_entries(&snippets.into_iter().map(Into::into).collect_vec()); } else { - let group = Group::from_qualified_name_and_snippets(group_name, snippets); + let group = Group::from_name_and_project_and_snippets(group_name, project, snippets); favorites_grouping.insert(0, group); } self.grouping_and_order_of_favorites = component::group::List::new(favorites_grouping); @@ -456,23 +459,22 @@ mod tests { /// inserted into an existing favorites group. #[test] fn building_component_list_with_virtual_component_in_existing_favorites_group() { - use component::group; let logger = Logger::new("tests::virtual_component_in_existing_favorites_group"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_lib = project::QualifiedName::standard_base_library(); - let qn_of_group = group::QualifiedName::new(qn_of_base_lib, "Group"); + let project = project::QualifiedName::standard_base_library(); + const GROUP_NAME: &str = "Group"; let groups = [execution_context::ComponentGroup { - project: qn_of_group.project.clone(), - name: qn_of_group.name.clone(), + project: project.clone(), + name: GROUP_NAME.into(), color: None, components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); - builder.insert_virtual_components_in_favorites_group(qn_of_group, snippet_iter); + builder.insert_virtual_components_in_favorites_group(GROUP_NAME, project, snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; @@ -485,24 +487,23 @@ mod tests { /// inserted into a new favorites group. #[test] fn building_component_list_with_virtual_component_in_new_favorites_group() { - use component::group; let logger = Logger::new("tests::virtual_component_in_new_favorites_group"); let db = mock_suggestion_db(logger); let mut builder = List::new(); let qn_of_db_entry_0 = db.lookup(0).unwrap().qualified_name(); - let qn_of_base_lib = project::QualifiedName::standard_base_library(); - let qn_of_group_1 = group::QualifiedName::new(qn_of_base_lib.clone(), "Group 1"); + let project = project::QualifiedName::standard_base_library(); + const GROUP_1_NAME: &str = "Group 1"; let groups = [execution_context::ComponentGroup { - project: qn_of_group_1.project.clone(), - name: qn_of_group_1.name, + project: project.clone(), + name: GROUP_1_NAME.into(), color: None, components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); - let qn_of_group_2 = group::QualifiedName::new(qn_of_base_lib, "Group 2"); - builder.insert_virtual_components_in_favorites_group(qn_of_group_2, snippet_iter); + const GROUP_2_NAME: &str = "Group 2"; + builder.insert_virtual_components_in_favorites_group(GROUP_2_NAME, project, snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); let list = builder.build(); let favorites = list.favorites; diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 8f2fcb670f6b..17953e0224cf 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -15,28 +15,6 @@ use std::cmp; -// ===================== -// === QualifiedName === -// ===================== - -/// Fully qualified name of a component group. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct QualifiedName { - /// Fully qualified name of the project containing the definition of the group. - pub project: project::QualifiedName, - /// The name of the group in the scope of the project where it was defined. - pub name: ImString, -} - -impl QualifiedName { - /// Construct. - pub fn new(project: project::QualifiedName, name: impl Into) -> Self { - Self { project, name: name.into() } - } -} - - - // ============ // === Data === // ============ @@ -128,14 +106,15 @@ impl Group { /// Create a group with given name and containing virtual components created from given /// snippets. - pub fn from_qualified_name_and_snippets( - qualified_name: QualifiedName, + pub fn from_name_and_project_and_snippets( + name: impl Into, + project: project::QualifiedName, snippets: impl IntoIterator>, ) -> Self { let entries = snippets.into_iter().map(Into::into).collect_vec(); let group_data = Data { - project: Some(qualified_name.project), - name: qualified_name.name, + project: Some(project), + name: name.into(), color: None, component_id: None, matched_items: Cell::new(entries.len()), @@ -242,12 +221,6 @@ impl Group { } } - /// The fully qualified name of the components group, or [`None`] if not available. - pub fn qualified_name(&self) -> Option { - let name = self.name.clone(); - self.project.as_ref().map(|p| QualifiedName { project: p.clone(), name }) - } - /// Get the number of entries. pub fn len(&self) -> usize { self.entries.borrow().len() From c7459485ec3680ebdab3b18bad0b1c81d4591d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 17:13:39 +0200 Subject: [PATCH 112/140] WIP create mod component::hardcoded and move type alias there --- app/gui/src/controller/searcher.rs | 8 ++++---- app/gui/src/controller/searcher/component.rs | 9 ++++----- app/gui/src/controller/searcher/component/builder.rs | 6 +++--- app/gui/src/controller/searcher/component/group.rs | 2 +- .../src/controller/searcher/component/hardcoded.rs | 11 +++++++++++ 5 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 app/gui/src/controller/searcher/component/hardcoded.rs diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 7b3d601202a5..8eebc5866d6b 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -57,7 +57,7 @@ thread_local! { /// Code snippets of default literal values of text and number type. The snippets are /// documented as code that can be used as input nodes. When converted to [`Component`]s and /// added to the [`component::List`] they allow the users to easily enter literals in code. - static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ + static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ LiteralSnippet { name: "text input", code: "\"\"", @@ -96,13 +96,13 @@ struct LiteralSnippet { pub icon: ide_view_component_group::icon::Id, } -impl TryFrom for component::HardcodedSnippet { +impl TryFrom for component::hardcoded::Snippet { type Error = failure::Error; - fn try_from(literal: LiteralSnippet) -> Result { + fn try_from(literal: LiteralSnippet) -> Result { let doc_parser = parser::DocParser::new()?; let doc_string = literal.documentation.to_string(); let documentation_html = doc_parser.generate_html_doc_pure(doc_string)?; - Ok(component::HardcodedSnippet { + Ok(component::hardcoded::Snippet { name: literal.name, code: literal.code, this_arg: None, diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8d74996f3699..8d5876c738f6 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -16,6 +16,7 @@ use convert_case::Casing; pub mod builder; pub mod group; +pub mod hardcoded; pub use group::Group; @@ -30,8 +31,6 @@ pub type Id = suggestion_database::entry::Id; /// Information how the component matches the filtering pattern. pub type MatchInfo = controller::searcher::action::MatchInfo; -/// A hardcoded snippet of code with a description and syntactic metadata. -pub type HardcodedSnippet = controller::searcher::action::hardcoded::Suggestion; // ============= @@ -73,7 +72,7 @@ pub enum Kind { /// A virtual component containing a hardcoded snippet of code. Virtual { /// A hardcoded snippet of code. - snippet: Rc, + snippet: Rc, }, } @@ -159,8 +158,8 @@ impl Component { } } -impl From> for Component { - fn from(snippet: Rc) -> Self { +impl From> for Component { + fn from(snippet: Rc) -> Self { Self { kind: Kind::Virtual { snippet }, match_info: default() } } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index f04b11d895b4..f125dd782d51 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -172,7 +172,7 @@ impl List { &mut self, group_name: &str, project: project::QualifiedName, - snippets: impl IntoIterator>, + snippets: impl IntoIterator>, ) { use component::Group; let mut favorites_grouping = self.take_grouping_and_order_of_favorites_as_vec(); @@ -472,7 +472,7 @@ mod tests { components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); - let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; + let snippet = component::hardcoded::Snippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); builder.insert_virtual_components_in_favorites_group(GROUP_NAME, project, snippet_iter); builder.extend_list_and_allow_favorites_with_ids(&db, std::iter::once(0)); @@ -500,7 +500,7 @@ mod tests { components: vec![qn_of_db_entry_0], }]; builder.set_grouping_and_order_of_favorites(&db, &groups); - let snippet = component::HardcodedSnippet { name: "test snippet", ..default() }; + let snippet = component::hardcoded::Snippet { name: "test snippet", ..default() }; let snippet_iter = std::iter::once(Rc::new(snippet)); const GROUP_2_NAME: &str = "Group 2"; builder.insert_virtual_components_in_favorites_group(GROUP_2_NAME, project, snippet_iter); diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 17953e0224cf..834a987f61e1 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -109,7 +109,7 @@ impl Group { pub fn from_name_and_project_and_snippets( name: impl Into, project: project::QualifiedName, - snippets: impl IntoIterator>, + snippets: impl IntoIterator>, ) -> Self { let entries = snippets.into_iter().map(Into::into).collect_vec(); let group_data = Data { diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs new file mode 100644 index 000000000000..66d35721e9dd --- /dev/null +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -0,0 +1,11 @@ + +use crate::prelude::*; + + + +// ==================== +// === Type Aliases === +// ==================== + +/// A hardcoded snippet of code with a description and syntactic metadata. +pub type Snippet = controller::searcher::action::hardcoded::Suggestion; From e383a199b3c675524dfe765789ebef3d6bde1744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 9 Aug 2022 17:56:46 +0200 Subject: [PATCH 113/140] WIP move stuff to mod hardcoded --- app/gui/src/controller/searcher.rs | 73 +------------------ .../searcher/component/hardcoded.rs | 73 +++++++++++++++++++ 2 files changed, 76 insertions(+), 70 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 8eebc5866d6b..4e8f99238fb9 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -49,73 +49,6 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; /// See also [`Searcher::add_enso_project_entries`]. const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; -/// Name of the virtual component group in the `Standard.Base` library which contains input -/// components. -const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; - -thread_local! { - /// Code snippets of default literal values of text and number type. The snippets are - /// documented as code that can be used as input nodes. When converted to [`Component`]s and - /// added to the [`component::List`] they allow the users to easily enter literals in code. - static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ - LiteralSnippet { - name: "text input", - code: "\"\"", - return_type: "Standard.Base.Data.Text.Text", - documentation: - "A text input node.\n\n\ - An empty text. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::TextInput, - }, - LiteralSnippet { - name: "number input", - code: "0", - return_type: "Standard.Base.Data.Numbers.Number", - documentation: - "A number input node.\n\n\ - A zero number. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::NumberInput, - }, - ].into_iter().map(|c| Rc::new(c.try_into().unwrap())).collect_vec(); -} - - - -// ====================== -// === LiteralSnippet === -// ====================== - -/// A snippet of code with a literal value, with description and syntax metadata. -struct LiteralSnippet { - pub name: &'static str, - pub code: &'static str, - pub return_type: &'static str, - pub documentation: &'static str, - pub icon: ide_view_component_group::icon::Id, -} - -impl TryFrom for component::hardcoded::Snippet { - type Error = failure::Error; - fn try_from(literal: LiteralSnippet) -> Result { - let doc_parser = parser::DocParser::new()?; - let doc_string = literal.documentation.to_string(); - let documentation_html = doc_parser.generate_html_doc_pure(doc_string)?; - Ok(component::hardcoded::Snippet { - name: literal.name, - code: literal.code, - this_arg: None, - argument_types: vec![], - return_type: Some(literal.return_type.try_into()?), - imports: vec![], - documentation_html: Some(documentation_html), - method_id: None, - icon: literal.icon.as_str().into(), - }) - } -} - // ============== @@ -1257,8 +1190,8 @@ fn component_list_builder_with_favorites<'a>( } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let base_lib_qn = project::QualifiedName::standard_base_library(); - let input_group_name = INPUT_COMPONENT_GROUP_NAME; - let snippets = LITERAL_INPUT_NODES_SNIPPETS.with(|snippet| snippet.clone()); + let input_group_name = component::hardcoded::INPUT_COMPONENT_GROUP_NAME; + let snippets = component::hardcoded::LITERAL_INPUT_NODES_SNIPPETS.with(|s| s.clone()); builder.insert_virtual_components_in_favorites_group(input_group_name, base_lib_qn, snippets); builder } @@ -1898,7 +1831,7 @@ pub mod test { let favorites = &components.favorites; assert_eq!(favorites.len(), 2); let favorites_group_0 = &favorites[0]; - assert_eq!(favorites_group_0.name, INPUT_COMPONENT_GROUP_NAME); + assert_eq!(favorites_group_0.name, component::hardcoded::INPUT_COMPONENT_GROUP_NAME); let favorites_group_1 = &favorites[1]; assert_eq!(favorites_group_1.name, "Test Group 1"); let favorites_entries = favorites_group_1.entries.borrow(); diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 66d35721e9dd..29c5c5ea5d0f 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -9,3 +9,76 @@ use crate::prelude::*; /// A hardcoded snippet of code with a description and syntactic metadata. pub type Snippet = controller::searcher::action::hardcoded::Suggestion; + + + +// ================= +// === Constants === +// ================= + +/// Name of the virtual component group in the `Standard.Base` library which contains input +/// components. +pub const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; + +thread_local! { + /// Code snippets of default literal values of text and number type. The snippets are + /// documented as code that can be used as input nodes. When converted to [`Component`]s and + /// added to the [`component::List`] they allow the users to easily enter literals in code. + pub static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ + LiteralSnippet { + name: "text input", + code: "\"\"", + return_type: "Standard.Base.Data.Text.Text", + documentation: + "A text input node.\n\n\ + An empty text. The value can be edited and used as an input for other nodes." + , + icon: ide_view_component_group::icon::Id::TextInput, + }, + LiteralSnippet { + name: "number input", + code: "0", + return_type: "Standard.Base.Data.Numbers.Number", + documentation: + "A number input node.\n\n\ + A zero number. The value can be edited and used as an input for other nodes." + , + icon: ide_view_component_group::icon::Id::NumberInput, + }, + ].into_iter().map(|c| Rc::new(c.try_into().unwrap())).collect_vec(); +} + + + +// ====================== +// === LiteralSnippet === +// ====================== + +/// A snippet of code with a literal value, with description and syntax metadata. +struct LiteralSnippet { + pub name: &'static str, + pub code: &'static str, + pub return_type: &'static str, + pub documentation: &'static str, + pub icon: ide_view_component_group::icon::Id, +} + +impl TryFrom for Snippet { + type Error = failure::Error; + fn try_from(literal: LiteralSnippet) -> Result { + let doc_parser = parser::DocParser::new()?; + let doc_string = literal.documentation.to_string(); + let documentation_html = doc_parser.generate_html_doc_pure(doc_string)?; + Ok(Snippet { + name: literal.name, + code: literal.code, + this_arg: None, + argument_types: vec![], + return_type: Some(literal.return_type.try_into()?), + imports: vec![], + documentation_html: Some(documentation_html), + method_id: None, + icon: literal.icon.as_str().into(), + }) + } +} From 4749c6efc9d145de2e4c77c2e9d834ab7d4ed90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 11:44:54 +0200 Subject: [PATCH 114/140] run enso-formatter on new files --- app/gui/src/controller/searcher/component/hardcoded.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 29c5c5ea5d0f..cc47ed17c888 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -1,4 +1,3 @@ - use crate::prelude::*; From c45e851a633f54c33c94095043bf98c5fb71c426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 11:56:43 +0200 Subject: [PATCH 115/140] WIP splitting LiteralSnippets static vector initialization --- .../searcher/component/hardcoded.rs | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index cc47ed17c888..3bcd5fe1e1e8 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -19,32 +19,34 @@ pub type Snippet = controller::searcher::action::hardcoded::Suggestion; /// components. pub const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; +const INPUT_NODES_LITERAL_SNIPPETS: &[LiteralSnippet] = &[ + LiteralSnippet { + name: "text input", + code: "\"\"", + return_type: "Standard.Base.Data.Text.Text", + documentation: + "A text input node.\n\n\ + An empty text. The value can be edited and used as an input for other nodes." + , + icon: ide_view_component_group::icon::Id::TextInput, + }, + LiteralSnippet { + name: "number input", + code: "0", + return_type: "Standard.Base.Data.Numbers.Number", + documentation: + "A number input node.\n\n\ + A zero number. The value can be edited and used as an input for other nodes." + , + icon: ide_view_component_group::icon::Id::NumberInput, + }, +]; + thread_local! { /// Code snippets of default literal values of text and number type. The snippets are /// documented as code that can be used as input nodes. When converted to [`Component`]s and /// added to the [`component::List`] they allow the users to easily enter literals in code. - pub static LITERAL_INPUT_NODES_SNIPPETS: Vec> = [ - LiteralSnippet { - name: "text input", - code: "\"\"", - return_type: "Standard.Base.Data.Text.Text", - documentation: - "A text input node.\n\n\ - An empty text. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::TextInput, - }, - LiteralSnippet { - name: "number input", - code: "0", - return_type: "Standard.Base.Data.Numbers.Number", - documentation: - "A number input node.\n\n\ - A zero number. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::NumberInput, - }, - ].into_iter().map(|c| Rc::new(c.try_into().unwrap())).collect_vec(); + pub static LITERAL_INPUT_NODES_SNIPPETS: Vec> = INPUT_NODES_LITERAL_SNIPPETS.into_iter().map(|c| Rc::new(c.clone().try_into().unwrap())).collect_vec(); } @@ -54,6 +56,7 @@ thread_local! { // ====================== /// A snippet of code with a literal value, with description and syntax metadata. +#[derive(Copy, Clone, Debug)] struct LiteralSnippet { pub name: &'static str, pub code: &'static str, From 71dba145aac169210e98a148e3d17af330fa3aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 13:00:35 +0200 Subject: [PATCH 116/140] WIP use Suggestion helpers to build INPUT_SNIPPETS --- app/gui/src/controller/searcher.rs | 2 +- .../controller/searcher/action/hardcoded.rs | 15 ++++++++-- .../searcher/component/hardcoded.rs | 29 +++++++++++++++++-- 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 4e8f99238fb9..2df03e875574 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1191,7 +1191,7 @@ fn component_list_builder_with_favorites<'a>( builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let base_lib_qn = project::QualifiedName::standard_base_library(); let input_group_name = component::hardcoded::INPUT_COMPONENT_GROUP_NAME; - let snippets = component::hardcoded::LITERAL_INPUT_NODES_SNIPPETS.with(|s| s.clone()); + let snippets = component::hardcoded::INPUT_SNIPPETS.with(|s| s.clone()); builder.insert_virtual_components_in_favorites_group(input_group_name, base_lib_qn, snippets); builder } diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index 5c31b5dc64dd..7abcad2526b6 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -110,7 +110,7 @@ pub struct Suggestion { } impl Suggestion { - fn new(name: &'static str, code: &'static str, icon: &ImString) -> Self { + pub(crate) fn new(name: &'static str, code: &'static str, icon: &ImString) -> Self { let icon = icon.clone_ref(); Self { name, code, icon, ..default() } } @@ -130,7 +130,7 @@ impl Suggestion { self } - fn with_return_type( + pub(crate) fn with_return_type( mut self, return_type: impl TryInto, ) -> Self { @@ -146,6 +146,17 @@ impl Suggestion { self } + pub(crate) fn with_documentation( + mut self, + documentation: &str, + ) -> Self { + let doc_parser = parser::DocParser::new().unwrap(); + let doc_string = documentation.to_string(); + let documentation_html = doc_parser.generate_html_doc_pure(doc_string); + self.documentation_html = Some(documentation_html.unwrap()); + self + } + fn marked_as_method_call( mut self, name: &'static str, diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 3bcd5fe1e1e8..c3040c2fdf43 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -19,7 +19,23 @@ pub type Snippet = controller::searcher::action::hardcoded::Suggestion; /// components. pub const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; -const INPUT_NODES_LITERAL_SNIPPETS: &[LiteralSnippet] = &[ +thread_local! { + /// Code snippets of default literal values of text and number type. The snippets are + /// documented as code that can be used as input nodes. When converted to [`Component`]s and + /// added to the [`component::List`] they allow the users to easily enter literals in code. + pub static INPUT_SNIPPETS: Vec> = vec![ + Snippet::new("text input", "\"\"", &ImString::new("TextInput")) + .with_return_type("Standard.Base.Data.Text.Text") + .with_documentation( + "A text input node.\n\n\ + An empty text. The value can be edited and used as an input for other nodes." + ) + .into(), + ]; +} + +/* +const INPUT_LITERAL_SNIPPETS: &[LiteralSnippet] = &[ LiteralSnippet { name: "text input", code: "\"\"", @@ -46,8 +62,17 @@ thread_local! { /// Code snippets of default literal values of text and number type. The snippets are /// documented as code that can be used as input nodes. When converted to [`Component`]s and /// added to the [`component::List`] they allow the users to easily enter literals in code. - pub static LITERAL_INPUT_NODES_SNIPPETS: Vec> = INPUT_NODES_LITERAL_SNIPPETS.into_iter().map(|c| Rc::new(c.clone().try_into().unwrap())).collect_vec(); + pub static INPUT_SNIPPETS: Vec> = build_input_snippets().unwrap(); +} + + +// === Constants helpers === + +fn build_input_snippets() -> FallibleResult>> { + let + INPUT_LITERAL_SNIPPETS.into_iter().map(|c| Rc::new(c.clone().try_into()?)).collect() } +*/ From 9058ced2e211705c8f39a62421818bdeca0b229c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 13:10:47 +0200 Subject: [PATCH 117/140] WIP finish migration & remove unused LiteralSnippet --- app/gui/src/controller/searcher.rs | 4 +- .../searcher/component/hardcoded.rs | 85 ++----------------- 2 files changed, 10 insertions(+), 79 deletions(-) diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index 2df03e875574..df4c8a083e4f 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -1190,7 +1190,7 @@ fn component_list_builder_with_favorites<'a>( } builder.set_grouping_and_order_of_favorites(suggestion_db, groups); let base_lib_qn = project::QualifiedName::standard_base_library(); - let input_group_name = component::hardcoded::INPUT_COMPONENT_GROUP_NAME; + let input_group_name = component::hardcoded::INPUT_GROUP_NAME; let snippets = component::hardcoded::INPUT_SNIPPETS.with(|s| s.clone()); builder.insert_virtual_components_in_favorites_group(input_group_name, base_lib_qn, snippets); builder @@ -1831,7 +1831,7 @@ pub mod test { let favorites = &components.favorites; assert_eq!(favorites.len(), 2); let favorites_group_0 = &favorites[0]; - assert_eq!(favorites_group_0.name, component::hardcoded::INPUT_COMPONENT_GROUP_NAME); + assert_eq!(favorites_group_0.name, component::hardcoded::INPUT_GROUP_NAME); let favorites_group_1 = &favorites[1]; assert_eq!(favorites_group_1.name, "Test Group 1"); let favorites_entries = favorites_group_1.entries.borrow(); diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index c3040c2fdf43..f1680df61e99 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -17,7 +17,7 @@ pub type Snippet = controller::searcher::action::hardcoded::Suggestion; /// Name of the virtual component group in the `Standard.Base` library which contains input /// components. -pub const INPUT_COMPONENT_GROUP_NAME: &str = "Input"; +pub const INPUT_GROUP_NAME: &str = "Input"; thread_local! { /// Code snippets of default literal values of text and number type. The snippets are @@ -31,81 +31,12 @@ thread_local! { An empty text. The value can be edited and used as an input for other nodes." ) .into(), + Snippet::new("number input", "0", &ImString::new("NumberInput")) + .with_return_type("Standard.Base.Data.Numbers.Number") + .with_documentation( + "A number input node.\n\n\ + A zero number. The value can be edited and used as an input for other nodes." + ) + .into(), ]; } - -/* -const INPUT_LITERAL_SNIPPETS: &[LiteralSnippet] = &[ - LiteralSnippet { - name: "text input", - code: "\"\"", - return_type: "Standard.Base.Data.Text.Text", - documentation: - "A text input node.\n\n\ - An empty text. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::TextInput, - }, - LiteralSnippet { - name: "number input", - code: "0", - return_type: "Standard.Base.Data.Numbers.Number", - documentation: - "A number input node.\n\n\ - A zero number. The value can be edited and used as an input for other nodes." - , - icon: ide_view_component_group::icon::Id::NumberInput, - }, -]; - -thread_local! { - /// Code snippets of default literal values of text and number type. The snippets are - /// documented as code that can be used as input nodes. When converted to [`Component`]s and - /// added to the [`component::List`] they allow the users to easily enter literals in code. - pub static INPUT_SNIPPETS: Vec> = build_input_snippets().unwrap(); -} - - -// === Constants helpers === - -fn build_input_snippets() -> FallibleResult>> { - let - INPUT_LITERAL_SNIPPETS.into_iter().map(|c| Rc::new(c.clone().try_into()?)).collect() -} -*/ - - - -// ====================== -// === LiteralSnippet === -// ====================== - -/// A snippet of code with a literal value, with description and syntax metadata. -#[derive(Copy, Clone, Debug)] -struct LiteralSnippet { - pub name: &'static str, - pub code: &'static str, - pub return_type: &'static str, - pub documentation: &'static str, - pub icon: ide_view_component_group::icon::Id, -} - -impl TryFrom for Snippet { - type Error = failure::Error; - fn try_from(literal: LiteralSnippet) -> Result { - let doc_parser = parser::DocParser::new()?; - let doc_string = literal.documentation.to_string(); - let documentation_html = doc_parser.generate_html_doc_pure(doc_string)?; - Ok(Snippet { - name: literal.name, - code: literal.code, - this_arg: None, - argument_types: vec![], - return_type: Some(literal.return_type.try_into()?), - imports: vec![], - documentation_html: Some(documentation_html), - method_id: None, - icon: literal.icon.as_str().into(), - }) - } -} From eb13f34d6ffc70073024aba4beed143a2f195783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 13:20:38 +0200 Subject: [PATCH 118/140] WIP snippet helper --- .../src/controller/searcher/component/hardcoded.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index f1680df61e99..34dc2471715c 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +use ide_view_component_group::icon::Id as IconId; + // ==================== @@ -24,14 +26,14 @@ thread_local! { /// documented as code that can be used as input nodes. When converted to [`Component`]s and /// added to the [`component::List`] they allow the users to easily enter literals in code. pub static INPUT_SNIPPETS: Vec> = vec![ - Snippet::new("text input", "\"\"", &ImString::new("TextInput")) + snippet_with_name_and_code_and_icon("text input", "\"\"", IconId::TextInput) .with_return_type("Standard.Base.Data.Text.Text") .with_documentation( "A text input node.\n\n\ An empty text. The value can be edited and used as an input for other nodes." ) .into(), - Snippet::new("number input", "0", &ImString::new("NumberInput")) + snippet_with_name_and_code_and_icon("number input", "0", IconId::NumberInput) .with_return_type("Standard.Base.Data.Numbers.Number") .with_documentation( "A number input node.\n\n\ @@ -40,3 +42,10 @@ thread_local! { .into(), ]; } + + +// === Constants helpers === + +fn snippet_with_name_and_code_and_icon(name: &'static str, code: &'static str, icon: IconId) -> Snippet { + Snippet::new(name, code, &ImString::new(icon.as_str())) +} From 7049e1ea33d3a5fe85b2f2b87461edaeb55c0304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 13:20:55 +0200 Subject: [PATCH 119/140] cargo fmt --- app/gui/src/controller/searcher/action/hardcoded.rs | 5 +---- app/gui/src/controller/searcher/component/hardcoded.rs | 6 +++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index 7abcad2526b6..9963cfc777e1 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -146,10 +146,7 @@ impl Suggestion { self } - pub(crate) fn with_documentation( - mut self, - documentation: &str, - ) -> Self { + pub(crate) fn with_documentation(mut self, documentation: &str) -> Self { let doc_parser = parser::DocParser::new().unwrap(); let doc_string = documentation.to_string(); let documentation_html = doc_parser.generate_html_doc_pure(doc_string); diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 34dc2471715c..56da891daac5 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -46,6 +46,10 @@ thread_local! { // === Constants helpers === -fn snippet_with_name_and_code_and_icon(name: &'static str, code: &'static str, icon: IconId) -> Snippet { +fn snippet_with_name_and_code_and_icon( + name: &'static str, + code: &'static str, + icon: IconId, +) -> Snippet { Snippet::new(name, code, &ImString::new(icon.as_str())) } From e045d841db8c9d06946edf345eb3716af19f2169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Wed, 10 Aug 2022 14:52:07 +0200 Subject: [PATCH 120/140] review: WIP fix other usages of "Base" --- app/gui/src/test.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/gui/src/test.rs b/app/gui/src/test.rs index e296a3ca0a77..8a5ac5ef35d1 100644 --- a/app/gui/src/test.rs +++ b/app/gui/src/test.rs @@ -97,12 +97,12 @@ pub mod mock { } pub fn suggestion_entry_foo() -> suggestion_database::Entry { - let project_name = project::QualifiedName::from_segments("std", "Base").unwrap(); + let project_name = project::QualifiedName::standard_base_library(); suggestion_database::Entry { name: "foo".to_owned(), module: module::QualifiedName::from_segments(project_name, &["Main"]) .unwrap(), - self_type: Some("std.Base.Main".to_owned().try_into().unwrap()), + self_type: Some("Standard.Base.Main".to_owned().try_into().unwrap()), arguments: vec![foo_method_parameter(), foo_method_parameter2()], return_type: "Any".to_owned(), kind: suggestion_database::entry::Kind::Method, @@ -113,12 +113,12 @@ pub mod mock { } pub fn suggestion_entry_bar() -> suggestion_database::Entry { - let project_name = project::QualifiedName::from_segments("std", "Base").unwrap(); + let project_name = project::QualifiedName::standard_base_library(); suggestion_database::Entry { name: "bar".to_owned(), module: module::QualifiedName::from_segments(project_name, &["Other"]) .unwrap(), - self_type: Some("std.Base.Other".to_owned().try_into().unwrap()), + self_type: Some("Standard.Base.Other".to_owned().try_into().unwrap()), arguments: vec![bar_method_parameter()], return_type: "Any".to_owned(), kind: suggestion_database::entry::Kind::Method, From 42da186db3b69464d749347b6b65cbc91c544ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 10:23:03 +0200 Subject: [PATCH 121/140] review: add constants for "Standard" and "Base" --- .../controller/double-representation/src/project.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index 601ef873c81b..db1c3bee47f7 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -9,6 +9,16 @@ use serde::Serialize; +// ================= +// === Constants === +// ================= + +const STANDARD_NAMESPACE: &str = "Standard"; + +const BASE_LIBRARY_NAME: &str = "Base"; + + + // ============== // === Errors === // ============== @@ -78,7 +88,7 @@ impl QualifiedName { /// Return the qualified name of the "Standard.Base" library project. pub fn standard_base_library() -> Self { - Self::from_segments("Standard", "Base").unwrap() + Self::from_segments(STANDARD_NAMESPACE, BASE_LIBRARY_NAME).unwrap() } /// The iterator over name's segments: the namespace and project name. From cea60f3f9329111a4395c592f77dfa7bcbdb696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 10:46:31 +0200 Subject: [PATCH 122/140] review: WIP Kind doc --- app/gui/src/controller/searcher/component.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 8d5876c738f6..5869cdcfa3be 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -59,6 +59,12 @@ pub enum Order { // === Kind === // ============ +/// Wraps the detailed data of a [`Component`]. The data differs depending on where the component +/// originates from (either from the [`suggestion_database`] or hardcoded). +/// Wraps the detailed data of a [`Component`]. The data is differentiated depending on where the component +/// originates from ( +/// Describes where a [`Component`] originates from (either +/// Differentiates /// The kind of a [`Component`]. #[derive(Clone, CloneRef, Debug)] pub enum Kind { From fa3b2c3f9d5db70bda3d870251af381fb5ebb1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:06:52 +0200 Subject: [PATCH 123/140] review: rename Kind to Data + update doc --- app/gui/src/controller/searcher/component.rs | 42 +++++++++---------- .../controller/searcher/component/builder.rs | 6 +-- app/gui/src/presenter/searcher.rs | 12 +++--- app/gui/src/presenter/searcher/provider.rs | 6 +-- 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 5869cdcfa3be..103ddfc79dac 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -56,18 +56,14 @@ pub enum Order { // ============ -// === Kind === +// === Data === // ============ -/// Wraps the detailed data of a [`Component`]. The data differs depending on where the component -/// originates from (either from the [`suggestion_database`] or hardcoded). -/// Wraps the detailed data of a [`Component`]. The data is differentiated depending on where the component -/// originates from ( -/// Describes where a [`Component`] originates from (either -/// Differentiates -/// The kind of a [`Component`]. +/// Contains detailed data of a [`Component`]. The details are stored as a reference that differs +/// depending on where the data originates from (either from the [`suggestion_database`] or from a +/// [`hardcoded::Snippet`]). #[derive(Clone, CloneRef, Debug)] -pub enum Kind { +pub enum Data { /// A component from the [`suggestion_database`]. FromDatabase { /// The ID of the component in the [`suggestion_database`]. @@ -99,7 +95,7 @@ pub enum Kind { #[allow(missing_docs)] #[derive(Clone, CloneRef, Debug)] pub struct Component { - pub kind: Kind, + pub data: Data, pub match_info: Rc>, } @@ -108,8 +104,8 @@ impl Component { /// /// The matching info will be filled for an empty pattern. pub fn new_from_database_entry(id: Id, entry: Rc) -> Self { - let kind = Kind::FromDatabase { id: Immutable(id), entry }; - Self { kind, match_info: default() } + let data = Data::FromDatabase { id: Immutable(id), entry }; + Self { data, match_info: default() } } /// The label which should be displayed in the Component Browser. @@ -119,17 +115,17 @@ impl Component { /// The name of the component. pub fn name(&self) -> &str { - match &self.kind { - Kind::FromDatabase { entry, .. } => entry.name.as_str(), - Kind::Virtual { snippet } => snippet.name, + match &self.data { + Data::FromDatabase { entry, .. } => entry.name.as_str(), + Data::Virtual { snippet } => snippet.name, } } /// The [`Id`] of the component in the [`suggestion_database`]. pub fn id(&self) -> Option { - match self.kind { - Kind::FromDatabase { id, .. } => Some(*id), - Kind::Virtual { .. } => None, + match self.data { + Data::FromDatabase { id, .. } => Some(*id), + Data::Virtual { .. } => None, } } @@ -144,7 +140,7 @@ impl Component { /// submodules of the entered module. pub fn can_be_entered(&self) -> bool { use suggestion_database::entry::Kind as EntryKind; - matches!(&self.kind, Kind::FromDatabase { entry, .. } if entry.kind == EntryKind::Module) + matches!(&self.data, Data::FromDatabase { entry, .. } if entry.kind == EntryKind::Module) } /// Update matching info. @@ -166,14 +162,14 @@ impl Component { impl From> for Component { fn from(snippet: Rc) -> Self { - Self { kind: Kind::Virtual { snippet }, match_info: default() } + Self { data: Data::Virtual { snippet }, match_info: default() } } } impl Display for Component { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.kind { - Kind::FromDatabase { entry, .. } => { + match &self.data { + Data::FromDatabase { entry, .. } => { let entry_name = entry.name.from_case(Case::Snake).to_case(Case::Lower); let self_type_ref = entry.self_type.as_ref(); let self_type_not_here = self_type_ref.filter(|t| *t != &entry.module); @@ -184,7 +180,7 @@ impl Display for Component { write!(f, "{}", entry_name) } } - Kind::Virtual { snippet } => write!(f, "{}", snippet.name), + Data::Virtual { snippet } => write!(f, "{}", snippet.name), } } } diff --git a/app/gui/src/controller/searcher/component/builder.rs b/app/gui/src/controller/searcher/component/builder.rs index f125dd782d51..286e9f3d8df6 100644 --- a/app/gui/src/controller/searcher/component/builder.rs +++ b/app/gui/src/controller/searcher/component/builder.rs @@ -245,9 +245,9 @@ impl List { fn build_favorites_and_add_to_all_components(&mut self) -> component::group::List { let mut favorites_groups = self.take_grouping_and_order_of_favorites_as_vec(); for group in favorites_groups.iter_mut() { - group.retain_entries(|e| match e.kind { - component::Kind::FromDatabase { id, .. } => self.allowed_favorites.contains(&id), - component::Kind::Virtual { .. } => true, + group.retain_entries(|e| match e.data { + component::Data::FromDatabase { id, .. } => self.allowed_favorites.contains(&id), + component::Data::Virtual { .. } => true, }); self.all_components.extend(group.entries.borrow().iter().cloned()); } diff --git a/app/gui/src/presenter/searcher.rs b/app/gui/src/presenter/searcher.rs index ed7a928b24b4..ea99641134d7 100644 --- a/app/gui/src/presenter/searcher.rs +++ b/app/gui/src/presenter/searcher.rs @@ -135,10 +135,10 @@ impl Model { let component: FallibleResult<_> = self.component_by_view_id(id).ok_or_else(|| NoSuchComponent(id).into()); let new_code = component.and_then(|component| { - let suggestion = match component.kind { - component::Kind::FromDatabase { entry, .. } => + let suggestion = match component.data { + component::Data::FromDatabase { entry, .. } => Suggestion::FromDatabase(entry.clone_ref()), - component::Kind::Virtual { snippet } => Suggestion::Hardcoded(snippet.clone_ref()), + component::Data::Virtual { snippet } => Suggestion::Hardcoded(snippet.clone_ref()), }; self.controller.use_suggestion(suggestion) }); @@ -206,8 +206,8 @@ impl Model { ) -> String { let component = id.and_then(|id| self.component_by_view_id(id)); if let Some(component) = component { - match component.kind { - component::Kind::FromDatabase { entry, .. } => { + match component.data { + component::Data::FromDatabase { entry, .. } => { if let Some(documentation) = &entry.documentation_html { let title = title_for_docs(&entry); format!( @@ -217,7 +217,7 @@ impl Model { doc_placeholder_for(&entry) } } - component::Kind::Virtual { snippet } => { + component::Data::Virtual { snippet } => { if let Some(documentation) = &snippet.documentation_html { documentation.to_string() } else { diff --git a/app/gui/src/presenter/searcher/provider.rs b/app/gui/src/presenter/searcher/provider.rs index 135c3cad7014..1fccb240dc0a 100644 --- a/app/gui/src/presenter/searcher/provider.rs +++ b/app/gui/src/presenter/searcher/provider.rs @@ -186,14 +186,14 @@ impl list_view::entry::ModelProvider for Component let match_info = component.match_info.borrow(); let label = component.label(); let highlighted = bytes_of_matched_letters(&*match_info, &label); - let icon = match component.kind { - component::Kind::FromDatabase { entry, .. } => { + let icon = match component.data { + component::Data::FromDatabase { entry, .. } => { let kind = entry.kind; let icon_name = entry.icon_name.as_ref(); let icon = icon_name.and_then(|n| n.to_pascal_case().parse().ok()); icon.unwrap_or_else(|| for_each_kind_variant!(kind_to_icon(kind))) } - component::Kind::Virtual { snippet } => { + component::Data::Virtual { snippet } => { let icon = &snippet.icon; let parsed_icon = component_group_view::icon::Id::from_str(icon); parsed_icon.unwrap_or_else(|_| { From 969cd9291f60fd6db0d211c02e7935325f784dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:19:22 +0200 Subject: [PATCH 124/140] docs for consts --- app/gui/controller/double-representation/src/project.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index db1c3bee47f7..7e595c3757b1 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -13,8 +13,10 @@ use serde::Serialize; // === Constants === // ================= +/// The namespace of the standard library. const STANDARD_NAMESPACE: &str = "Standard"; +/// The name of the project in the [`STANDARD_NAMESPACE`] containing the base standard library. const BASE_LIBRARY_NAME: &str = "Base"; From 297a502e1cc6406c3fd87961a6c2985a057636d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:33:06 +0200 Subject: [PATCH 125/140] first docs tweaks in mod hardcoded --- app/gui/src/controller/searcher/component/hardcoded.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 56da891daac5..6444fda606de 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -1,3 +1,7 @@ +//! A module containing definitions of hardcoded [`Snippet`]s displayed as virtual components in +//! the [Component Browser](crate::controller::Searcher). The module also defines names of the +//! virtual component groups where the snippets should be added. + use crate::prelude::*; use ide_view_component_group::icon::Id as IconId; @@ -17,8 +21,8 @@ pub type Snippet = controller::searcher::action::hardcoded::Suggestion; // === Constants === // ================= -/// Name of the virtual component group in the `Standard.Base` library which contains input -/// components. +/// Name of the virtual component group in the `Standard.Base` library where virtual components +/// created from the [`INPUT_SNIPPETS`] should be added. pub const INPUT_GROUP_NAME: &str = "Input"; thread_local! { From 9152c11b1f2ddd1448e40972ec610dcbb4215e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:41:31 +0200 Subject: [PATCH 126/140] WIP more doc tweaks --- app/gui/src/controller/searcher/component/hardcoded.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 6444fda606de..986cae4b09a4 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -1,6 +1,9 @@ //! A module containing definitions of hardcoded [`Snippet`]s displayed as virtual components in //! the [Component Browser](crate::controller::Searcher). The module also defines names of the -//! virtual component groups where the snippets should be added. +//! favorites component groups where the snippets should be added. +//! +//! To learn more about favorites component groups, see: +//! [`crate::controller::searcher::component::List::favorites`]. use crate::prelude::*; @@ -21,11 +24,14 @@ pub type Snippet = controller::searcher::action::hardcoded::Suggestion; // === Constants === // ================= -/// Name of the virtual component group in the `Standard.Base` library where virtual components +/// Name of the favorites component group in the `Standard.Base` library where virtual components /// created from the [`INPUT_SNIPPETS`] should be added. pub const INPUT_GROUP_NAME: &str = "Input"; thread_local! { + /// Snippets describing virtual components displayed in the [`INPUT_GROUP_NAME`] favorites + /// component group. + /// Code snippets /// Code snippets of default literal values of text and number type. The snippets are /// documented as code that can be used as input nodes. When converted to [`Component`]s and /// added to the [`component::List`] they allow the users to easily enter literals in code. From bb7a481ae4852b5091fddd626774cb720343475f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:52:00 +0200 Subject: [PATCH 127/140] tweak doc of INPUT_SNIPPETS --- app/gui/src/controller/searcher/component/hardcoded.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/gui/src/controller/searcher/component/hardcoded.rs b/app/gui/src/controller/searcher/component/hardcoded.rs index 986cae4b09a4..99ad5ff69bc5 100644 --- a/app/gui/src/controller/searcher/component/hardcoded.rs +++ b/app/gui/src/controller/searcher/component/hardcoded.rs @@ -1,6 +1,6 @@ //! A module containing definitions of hardcoded [`Snippet`]s displayed as virtual components in //! the [Component Browser](crate::controller::Searcher). The module also defines names of the -//! favorites component groups where the snippets should be added. +//! favorites component groups where the virtual components should be displayed. //! //! To learn more about favorites component groups, see: //! [`crate::controller::searcher::component::List::favorites`]. @@ -30,11 +30,9 @@ pub const INPUT_GROUP_NAME: &str = "Input"; thread_local! { /// Snippets describing virtual components displayed in the [`INPUT_GROUP_NAME`] favorites - /// component group. - /// Code snippets - /// Code snippets of default literal values of text and number type. The snippets are - /// documented as code that can be used as input nodes. When converted to [`Component`]s and - /// added to the [`component::List`] they allow the users to easily enter literals in code. + /// component group. The snippets wrap default literal values of Text and Number types. When + /// displayed in the Component Browser as virtual components they allow the users to easily + /// enter primitive literals in code. pub static INPUT_SNIPPETS: Vec> = vec![ snippet_with_name_and_code_and_icon("text input", "\"\"", IconId::TextInput) .with_return_type("Standard.Base.Data.Text.Text") From d94aece2726764759cdf024a9531b424a91de758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 11:54:05 +0200 Subject: [PATCH 128/140] tweak doc of standard_base_library --- app/gui/controller/double-representation/src/project.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index 7e595c3757b1..d8554399153c 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -88,7 +88,8 @@ impl QualifiedName { } } - /// Return the qualified name of the "Standard.Base" library project. + /// Return the qualified name of the [`BASE_LIBRARY_NAME`] project in the + /// [`STANDARD_NAMESPACE`]. pub fn standard_base_library() -> Self { Self::from_segments(STANDARD_NAMESPACE, BASE_LIBRARY_NAME).unwrap() } From 73287eb78902ca2e3b31d8ba37e26a519dfe2474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:03:31 +0200 Subject: [PATCH 129/140] STANDARD_BASE_LIBRARY_PATH --- Cargo.lock | 2 ++ app/gui/Cargo.toml | 1 + app/gui/controller/double-representation/Cargo.toml | 1 + .../controller/double-representation/src/project.rs | 10 +++++++--- app/gui/src/controller/searcher.rs | 4 +++- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94900bd211ff..f2d94a1920e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1659,6 +1659,7 @@ name = "double-representation" version = "0.1.0" dependencies = [ "ast", + "const_format", "engine-protocol", "enso-data-structures", "enso-logger", @@ -1960,6 +1961,7 @@ dependencies = [ "ast", "bimap", "console_error_panic_hook", + "const_format", "convert_case 0.5.0", "double-representation", "engine-protocol", diff --git a/app/gui/Cargo.toml b/app/gui/Cargo.toml index 0b40465b420c..a1ce7d25937c 100644 --- a/app/gui/Cargo.toml +++ b/app/gui/Cargo.toml @@ -38,6 +38,7 @@ parser = { path = "language/parser" } span-tree = { path = "language/span-tree" } bimap = { version = "0.4.0" } console_error_panic_hook = { version = "0.1.6" } +const_format = { version = "0.2.22" } convert_case = { version = "0.5.0" } failure = { version = "0.1.6" } flo_stream = { version = "0.4.0" } diff --git a/app/gui/controller/double-representation/Cargo.toml b/app/gui/controller/double-representation/Cargo.toml index ff13fc5c9309..76ac5113cb95 100644 --- a/app/gui/controller/double-representation/Cargo.toml +++ b/app/gui/controller/double-representation/Cargo.toml @@ -16,6 +16,7 @@ enso-logger = { path = "../../../../lib/rust/logger" } enso-prelude = { path = "../../../../lib/rust/prelude" } enso-profiler = { path = "../../../../lib/rust/profiler" } enso-text = { path = "../../../../lib/rust/text" } +const_format = { version = "0.2.22" } failure = { version = "0.1.6" } itertools = { version = "0.10.0" } serde = { version = "1.0", features = ["derive"] } diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index d8554399153c..68c8671922d7 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -4,6 +4,7 @@ use crate::prelude::*; use crate::identifier::ReferentName; +use const_format::concatcp; use serde::Deserialize; use serde::Serialize; @@ -14,10 +15,13 @@ use serde::Serialize; // ================= /// The namespace of the standard library. -const STANDARD_NAMESPACE: &str = "Standard"; +pub const STANDARD_NAMESPACE: &str = "Standard"; /// The name of the project in the [`STANDARD_NAMESPACE`] containing the base standard library. -const BASE_LIBRARY_NAME: &str = "Base"; +pub const BASE_LIBRARY_NAME: &str = "Base"; + +/// The path of the [`BASE_LIBRARY_NAME`] project in the [`STANDARD_NAMESPACE`]. +pub const STANDARD_BASE_LIBRARY_PATH: &str = concatcp!(STANDARD_NAMESPACE, ".", BASE_LIBRARY_NAME); @@ -88,7 +92,7 @@ impl QualifiedName { } } - /// Return the qualified name of the [`BASE_LIBRARY_NAME`] project in the + /// Return the fully qualified name of the [`BASE_LIBRARY_NAME`] project in the /// [`STANDARD_NAMESPACE`]. pub fn standard_base_library() -> Self { Self::from_segments(STANDARD_NAMESPACE, BASE_LIBRARY_NAME).unwrap() diff --git a/app/gui/src/controller/searcher.rs b/app/gui/src/controller/searcher.rs index df4c8a083e4f..5af129652c2a 100644 --- a/app/gui/src/controller/searcher.rs +++ b/app/gui/src/controller/searcher.rs @@ -13,6 +13,7 @@ use crate::model::suggestion_database; use crate::model::suggestion_database::entry::CodeToInsert; use crate::notification; +use const_format::concatcp; use double_representation::graph::GraphInfo; use double_representation::graph::LocationHint; use double_representation::module::QualifiedName; @@ -47,7 +48,8 @@ pub const ASSIGN_NAMES_FOR_NODES: bool = true; /// The special module used for mock `Enso_Project.data` entry. /// See also [`Searcher::add_enso_project_entries`]. -const ENSO_PROJECT_SPECIAL_MODULE: &str = "Standard.Base.Enso_Project"; +const ENSO_PROJECT_SPECIAL_MODULE: &str = + concatcp!(project::STANDARD_BASE_LIBRARY_PATH, ".Enso_Project"); From 534d6003689eca673f1d616d8388c787bc155791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:06:29 +0200 Subject: [PATCH 130/140] small tweak: +full --- app/gui/controller/double-representation/src/project.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/controller/double-representation/src/project.rs b/app/gui/controller/double-representation/src/project.rs index 68c8671922d7..2993b7f61bf5 100644 --- a/app/gui/controller/double-representation/src/project.rs +++ b/app/gui/controller/double-representation/src/project.rs @@ -20,7 +20,7 @@ pub const STANDARD_NAMESPACE: &str = "Standard"; /// The name of the project in the [`STANDARD_NAMESPACE`] containing the base standard library. pub const BASE_LIBRARY_NAME: &str = "Base"; -/// The path of the [`BASE_LIBRARY_NAME`] project in the [`STANDARD_NAMESPACE`]. +/// The full path of the [`BASE_LIBRARY_NAME`] project in the [`STANDARD_NAMESPACE`]. pub const STANDARD_BASE_LIBRARY_PATH: &str = concatcp!(STANDARD_NAMESPACE, ".", BASE_LIBRARY_NAME); From 7fccc488b78e32f57dfe619681b3a3c91ef335e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:25:37 +0200 Subject: [PATCH 131/140] add docs for suggestion methods --- app/gui/src/controller/searcher/action/hardcoded.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index 9963cfc777e1..b090e8d4025e 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -110,6 +110,7 @@ pub struct Suggestion { } impl Suggestion { + /// Construct a suggestion with given name, code, and icon. pub(crate) fn new(name: &'static str, code: &'static str, icon: &ImString) -> Self { let icon = icon.clone_ref(); Self { name, code, icon, ..default() } @@ -130,6 +131,9 @@ impl Suggestion { self } + /// Return a modified suggestion with [`Suggestion::return_type`] field set. This method is + /// only intended to be used to define hardcoded suggestions as it panics if the argument fails + /// to convert to a valid type name. pub(crate) fn with_return_type( mut self, return_type: impl TryInto, @@ -146,6 +150,9 @@ impl Suggestion { self } + /// Return a modified suggestion with [`Suggestion::documentation_html`] field set. This method + /// is only intended to be used to define hardcoded suggestions as it panics if the argument + /// fails to parse as valid documentation. pub(crate) fn with_documentation(mut self, documentation: &str) -> Self { let doc_parser = parser::DocParser::new().unwrap(); let doc_string = documentation.to_string(); From 0608afefb671a7d34d1d564d2251865adde1a7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:33:25 +0200 Subject: [PATCH 132/140] tweak method helpers docs --- app/gui/src/controller/searcher/action/hardcoded.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index b090e8d4025e..b988a3253992 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -131,9 +131,9 @@ impl Suggestion { self } - /// Return a modified suggestion with [`Suggestion::return_type`] field set. This method is - /// only intended to be used to define hardcoded suggestions as it panics if the argument fails - /// to convert to a valid type name. + /// Returns a modified suggestion with [`Suggestion::return_type`] field set. This method is + /// only intended to be used when defining hardcoded suggestions and panics if the argument + /// fails to convert to a valid type name. pub(crate) fn with_return_type( mut self, return_type: impl TryInto, @@ -150,9 +150,9 @@ impl Suggestion { self } - /// Return a modified suggestion with [`Suggestion::documentation_html`] field set. This method - /// is only intended to be used to define hardcoded suggestions as it panics if the argument - /// fails to parse as valid documentation. + /// Returns a modified suggestion with [`Suggestion::documentation_html`] field set. This + /// method is only intended to be used when defining hardcoded suggestions and panics if the + /// argument fails to parse as valid documentation. pub(crate) fn with_documentation(mut self, documentation: &str) -> Self { let doc_parser = parser::DocParser::new().unwrap(); let doc_string = documentation.to_string(); From a022cc57854b73fe338bc4c66047ffa4acaaaf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:34:55 +0200 Subject: [PATCH 133/140] mention parser panic --- app/gui/src/controller/searcher/action/hardcoded.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index b988a3253992..c53472c114e0 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -151,8 +151,9 @@ impl Suggestion { } /// Returns a modified suggestion with [`Suggestion::documentation_html`] field set. This - /// method is only intended to be used when defining hardcoded suggestions and panics if the - /// argument fails to parse as valid documentation. + /// method is only intended to be used when defining hardcoded suggestions and panics if a + /// documentation parser cannot be created or the argument fails to parse as valid + /// documentation. pub(crate) fn with_documentation(mut self, documentation: &str) -> Self { let doc_parser = parser::DocParser::new().unwrap(); let doc_string = documentation.to_string(); From 567bab33c21d8b7fa5b1f769acc121075b4320a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:38:07 +0200 Subject: [PATCH 134/140] tweak doc of Data --- app/gui/src/controller/searcher/component.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 103ddfc79dac..465c9cdc771a 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -59,8 +59,8 @@ pub enum Order { // === Data === // ============ -/// Contains detailed data of a [`Component`]. The details are stored as a reference that differs -/// depending on where the data originates from (either from the [`suggestion_database`] or from a +/// Contains detailed data of a [`Component`]. The storage of the details differs depending on +/// where the data originates from (either from the [`suggestion_database`] or from a /// [`hardcoded::Snippet`]). #[derive(Clone, CloneRef, Debug)] pub enum Data { From 02e60e55a8a8c95f8752fc9a5ff3458dcee237d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:39:57 +0200 Subject: [PATCH 135/140] tweak comment of fn id --- app/gui/src/controller/searcher/component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index 465c9cdc771a..faade66aaac2 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -121,7 +121,7 @@ impl Component { } } - /// The [`Id`] of the component in the [`suggestion_database`]. + /// The [`Id`] of the component in the [`suggestion_database`], or `None` if not applicable. pub fn id(&self) -> Option { match self.data { Data::FromDatabase { id, .. } => Some(*id), From ac520770efafca1cfeecf6d80a31c5c06a4048fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:47:22 +0200 Subject: [PATCH 136/140] tweak doc of from_n_and_p_and_snippets --- app/gui/src/controller/searcher/component/group.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 834a987f61e1..6929097223d0 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -104,8 +104,8 @@ impl Group { Self::from_name_and_project_and_id(name, Some(project_name), Some(component_id)) } - /// Create a group with given name and containing virtual components created from given - /// snippets. + /// Create a group with given name in given project and containing virtual components created + /// from given snippets. pub fn from_name_and_project_and_snippets( name: impl Into, project: project::QualifiedName, From ab701f165ea30a9e6635f254ab5a39bb23b87ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Thu, 11 Aug 2022 12:50:41 +0200 Subject: [PATCH 137/140] bring back some code in test --- app/gui/src/controller/searcher/component/group.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/gui/src/controller/searcher/component/group.rs b/app/gui/src/controller/searcher/component/group.rs index 6929097223d0..e7e5b67fdc3f 100644 --- a/app/gui/src/controller/searcher/component/group.rs +++ b/app/gui/src/controller/searcher/component/group.rs @@ -362,9 +362,15 @@ mod tests { assert_eq!((color.red * 255.0) as u8, 0xaa); assert_eq!((color.green * 255.0) as u8, 0xbb); assert_eq!((color.blue * 255.0) as u8, 0xcc); - let entry_ids = group.entries.borrow().iter().map(|e| e.id().unwrap()).collect_vec(); - let expected_ids = vec![6, 10, 5]; - assert_eq!(entry_ids, expected_ids); + let entry_ids_and_names = group + .entries + .borrow() + .iter() + .map(|e| (e.id().unwrap(), e.name().to_string())) + .collect_vec(); + let expected_ids_and_names = + vec![(6, "fun2".to_string()), (10, "fun6".to_string()), (5, "fun1".to_string())]; + assert_eq!(entry_ids_and_names, expected_ids_and_names); } // Test constructing a component group from an [`execution_context::ComponentGroup`] containing From ef6fda103e2a83ef2fda74d5acaf0d5b15585e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 16 Aug 2022 14:23:07 +0200 Subject: [PATCH 138/140] review: doc of Suggestion::new func Co-authored-by: Adam Obuchowicz --- app/gui/src/controller/searcher/action/hardcoded.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/gui/src/controller/searcher/action/hardcoded.rs b/app/gui/src/controller/searcher/action/hardcoded.rs index c53472c114e0..02276648e5c3 100644 --- a/app/gui/src/controller/searcher/action/hardcoded.rs +++ b/app/gui/src/controller/searcher/action/hardcoded.rs @@ -110,7 +110,7 @@ pub struct Suggestion { } impl Suggestion { - /// Construct a suggestion with given name, code, and icon. + /// Construct a hardcoded suggestion with given name, code, and icon. pub(crate) fn new(name: &'static str, code: &'static str, icon: &ImString) -> Self { let icon = icon.clone_ref(); Self { name, code, icon, ..default() } From 7b781213de7c2f6caed9f539a72ec20d9ebd1b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 16 Aug 2022 14:47:45 +0200 Subject: [PATCH 139/140] review: tweak doc comments --- app/gui/src/controller/searcher/component.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index faade66aaac2..abde927c22df 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -64,14 +64,17 @@ pub enum Order { /// [`hardcoded::Snippet`]). #[derive(Clone, CloneRef, Debug)] pub enum Data { - /// A component from the [`suggestion_database`]. + /// A component from the [`suggestion_database`]. When this component is picked in the + /// Component Browser, the stored [`suggestion_database::Entry`] will be used to insert code + /// into the program. FromDatabase { /// The ID of the component in the [`suggestion_database`]. id: Immutable, /// The component's entry in the [`suggestion_database`]. entry: Rc, }, - /// A virtual component containing a hardcoded snippet of code. + /// A virtual component containing a hardcoded snippet of code. When this component is picked + /// in the Component Browser, the [`Snippet::code`] will be inserted into the program. Virtual { /// A hardcoded snippet of code. snippet: Rc, @@ -90,8 +93,8 @@ pub enum Data { /// The components are usually stored in [`List`], which may be filtered; the single component keeps /// then information how it matches the current filtering pattern. /// -/// The component corresponds to some Suggestion Database Entry, and the entry will be used to -/// properly insert code into the program. +/// See the documentation of the [`Data`] variants for information on what will happen when the +/// component is picked in the Component Browser panel. #[allow(missing_docs)] #[derive(Clone, CloneRef, Debug)] pub struct Component { From 5126554f73f2292655550769fab43c2e0aac0186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Czapli=C5=84ski?= Date: Tue, 16 Aug 2022 15:05:42 +0200 Subject: [PATCH 140/140] review: tweak doc --- app/gui/src/controller/searcher/component.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/gui/src/controller/searcher/component.rs b/app/gui/src/controller/searcher/component.rs index abde927c22df..c3a002985404 100644 --- a/app/gui/src/controller/searcher/component.rs +++ b/app/gui/src/controller/searcher/component.rs @@ -65,8 +65,8 @@ pub enum Order { #[derive(Clone, CloneRef, Debug)] pub enum Data { /// A component from the [`suggestion_database`]. When this component is picked in the - /// Component Browser, the stored [`suggestion_database::Entry`] will be used to insert code - /// into the program. + /// Component Browser, the code returned by [`suggestion_database::Entry::code_to_insert`] will + /// be inserted into the program. FromDatabase { /// The ID of the component in the [`suggestion_database`]. id: Immutable,