From b63ea789f84603f764428b0b59fda6953dbf8c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Wawrzyniec=20Urba=C5=84czyk?= Date: Tue, 16 Feb 2021 11:33:55 +0100 Subject: [PATCH] Nodes added by searcher will always use assignment form. (#1198) --- CHANGELOG.md | 3 ++ src/rust/Cargo.toml | 2 +- src/rust/ide/src/controller/graph.rs | 44 +++++++++++++++++++------ src/rust/ide/src/controller/searcher.rs | 29 +++++++++++----- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b7c8db2ab..154db2ab47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ read the notes of the `Enso 2.0.0-alpha.1` release. - [Documentation in Searcher][1098]. Fixed cases where text would be misinterpreted as tag, added support for new tag types, added support for more common characters, properly renders overflowing text. +- [Assigning intermediate expressions to values][1067]. Nodes added with searcher will have their + values automatically assigned to a newly generated variables. This allows Enso Engine to cache + intermediate values, improving visualization performance. #### EnsoGL - New multi-camera management system, allowing the same shape systems be rendered on different diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 370d0e2015..1a2076f3d6 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -33,7 +33,7 @@ members = [ ] [profile.dev] -opt-level = 2 +opt-level = 0 lto = false debug = true diff --git a/src/rust/ide/src/controller/graph.rs b/src/rust/ide/src/controller/graph.rs index 8b11d9dff1..7775a317e6 100644 --- a/src/rust/ide/src/controller/graph.rs +++ b/src/rust/ide/src/controller/graph.rs @@ -103,17 +103,21 @@ pub struct NewNodeInfo { /// ID to be given to the node. pub id : Option, /// Where line created by adding this node should appear. - pub location_hint : LocationHint + pub location_hint : LocationHint, + /// Introduce variable name for the node, making it into an assignment line. + pub introduce_pattern : bool, + } impl NewNodeInfo { /// New node with given expression added at the end of the graph's blocks. pub fn new_pushed_back(expression:impl Str) -> NewNodeInfo { NewNodeInfo { - expression : expression.into(), - metadata : default(), - id : default(), - location_hint : LocationHint::End, + expression : expression.into(), + metadata : default(), + id : default(), + location_hint : LocationHint::End, + introduce_pattern : default(), } } } @@ -715,6 +719,11 @@ impl Handle { node_info.set_id(desired_id) } + if node.introduce_pattern && node_info.pattern().is_none() { + let var = self.variable_name_for(&node_info)?; + node_info.set_pattern(var.into()); + } + self.update_definition_ast(|definition| { let mut graph = GraphInfo::from_definition(definition); let node_ast = node_info.ast().clone(); @@ -1244,12 +1253,13 @@ main = let position = Some(model::module::Position::new(10.0,20.0)); let metadata = NodeMetadata {position,..default()}; let info = NewNodeInfo { - expression : "a+b".into(), - metadata : Some(metadata), - id : Some(id), - location_hint : LocationHint::End, + expression : "a+b".into(), + metadata : Some(metadata), + id : Some(id), + location_hint : LocationHint::End, + introduce_pattern : false, }; - graph.add_node(info).unwrap(); + graph.add_node(info.clone()).unwrap(); let expected_program = r" main = foo = 2 @@ -1283,6 +1293,20 @@ main = assert!(graph.module.node_metadata(id).is_err()); model::module::test::expect_code(&*graph.module, PROGRAM); + + + // === Test adding node with automatically generated pattern === + let info_w_pattern = NewNodeInfo { + introduce_pattern : true, + ..info + }; + graph.add_node(info_w_pattern).unwrap(); + let expected_program = r" +main = + foo = 2 + print foo + sum1 = a+b"; + model::module::test::expect_code(&*graph.module,expected_program); }) } diff --git a/src/rust/ide/src/controller/searcher.rs b/src/rust/ide/src/controller/searcher.rs index 229f1ffdc7..dab49f82eb 100644 --- a/src/rust/ide/src/controller/searcher.rs +++ b/src/rust/ide/src/controller/searcher.rs @@ -23,6 +23,16 @@ pub use action::Action; +// ================= +// === Constants === +// ================= + +/// If enabled, searcher will assign names for all nodes created with it, not only when it is +/// needed. Currently enabled to trigger engine's caching of user-added nodes. +/// See: https://github.com/enso-org/ide/issues/1067 +pub const ASSIGN_NAMES_FOR_NODES:bool = true; + + // ============== // === Errors === @@ -649,8 +659,9 @@ impl Searcher { let id = match *self.mode { Mode::NewNode {position} => { - let mut new_node = NewNodeInfo::new_pushed_back(expression); - new_node.metadata = Some(NodeMetadata {position,intended_method}); + let mut new_node = NewNodeInfo::new_pushed_back(expression); + new_node.metadata = Some(NodeMetadata {position,intended_method}); + new_node.introduce_pattern = ASSIGN_NAMES_FOR_NODES; let graph = self.graph.graph(); if let Some(this) = self.this_arg.deref().as_ref() { this.introduce_pattern(graph.clone_ref())?; @@ -1553,26 +1564,26 @@ pub mod test { let cases = vec![ // Completion was picked. - Case::new("2 + 2",&["sum1 = 2 + 2","sum1.testFunction1"], |f| { + Case::new("2 + 2",&["sum1 = 2 + 2","operator1 = sum1.testFunction1"], |f| { f.searcher.use_suggestion(f.entry1.clone()).unwrap(); }), // The input was manually written (not picked). - Case::new("2 + 2",&["sum1 = 2 + 2","sum1.testFunction1"], |f| { + Case::new("2 + 2",&["sum1 = 2 + 2","operator1 = sum1.testFunction1"], |f| { f.searcher.set_input("testFunction1 ".to_owned()).unwrap(); }), // Completion was picked and edited. - Case::new("2 + 2",&["sum1 = 2 + 2","sum1.var.testFunction1"], |f| { + Case::new("2 + 2",&["sum1 = 2 + 2","operator1 = sum1.var.testFunction1"], |f| { f.searcher.use_suggestion(f.entry1.clone()).unwrap(); let new_parsed_input = ParsedInput::new("var.testFunction1",&f.searcher.parser); f.searcher.data.borrow_mut().input = new_parsed_input.unwrap(); }), // Variable name already present, need to use it. And not break it. - Case::new("my_var = 2 + 2",&["my_var = 2 + 2","my_var.testFunction1"], |f| { + Case::new("my_var = 2 + 2",&["my_var = 2 + 2","operator1 = my_var.testFunction1"], |f| { f.searcher.use_suggestion(f.entry1.clone()).unwrap(); }), // Variable names unusable (subpatterns are not yet supported). // Don't use "this" argument adjustments at all. - Case::new("[x,y] = 2 + 2",&["[x,y] = 2 + 2","testFunction1"], |f| { + Case::new("[x,y] = 2 + 2",&["[x,y] = 2 + 2","testfunction11 = testFunction1"], |f| { f.searcher.use_suggestion(f.entry1.clone()).unwrap(); }), ]; @@ -1610,7 +1621,7 @@ pub mod test { searcher.mode = Immutable(Mode::NewNode {position}); searcher.commit_node().unwrap(); - let expected_code = "import Test.Test\nmain = \n 2 + 2\n Test.testMethod1"; + let expected_code = "import Test.Test\nmain = \n 2 + 2\n operator1 = Test.testMethod1"; assert_eq!(module.ast().repr(), expected_code); let (node1,node2) = searcher.graph.graph().nodes().unwrap().expect_tuple(); let expected_intended_method = Some(MethodId { @@ -1623,7 +1634,7 @@ pub mod test { // Edit existing node. searcher.mode = Immutable(Mode::EditNode {node_id:node1.info.id()}); searcher.commit_node().unwrap(); - let expected_code = "import Test.Test\nmain = \n Test.testMethod1\n Test.testMethod1"; + let expected_code = "import Test.Test\nmain = \n Test.testMethod1\n operator1 = Test.testMethod1"; let (node1,_) = searcher.graph.graph().nodes().unwrap().expect_tuple(); assert_eq!(node1.metadata.unwrap().intended_method, expected_intended_method); assert_eq!(module.ast().repr(), expected_code);