From 675fb5c636ce8888cd811b65358971e6a11f6216 Mon Sep 17 00:00:00 2001 From: Craig Condon Date: Mon, 11 Sep 2023 22:05:11 -0600 Subject: [PATCH] ability to move text nodes and elements over --- libs/ast_serialize/src/pc.rs | 4 +- libs/compiler-react/src/code_compiler.rs | 3 +- libs/evaluator/src/css/evaluator.rs | 5 +- libs/parser/src/css/parser.rs | 5 +- libs/parser/src/pc/parser.rs | 11 +- libs/proto/build.rs | 1 + libs/proto/src/ast/all/mod.rs | 3 +- libs/proto/src/ast/all/visit.rs | 8 +- libs/proto/src/ast/css.proto | 11 +- libs/proto/src/ast/get_expr.rs | 4 +- libs/proto/src/ast/mod.rs | 1 + libs/proto/src/ast/pc.proto | 14 +- libs/proto/src/ast/pc.rs | 26 +++ libs/proto/src/ast/shared.proto | 10 ++ libs/proto/src/ast/shared.rs | 39 +++++ libs/proto/src/ast_mutate/mod.proto | 7 + libs/proto_ext/scripts/build.sh | 2 +- libs/proto_ext/src/ast/get_expr.rs | 85 --------- libs/proto_ext/src/ast/mod.rs | 1 - libs/proto_ext/src/ast_mutate/add_import.rs | 15 ++ libs/proto_ext/src/ast_mutate/base.rs | 7 + libs/proto_ext/src/ast_mutate/mod.rs | 21 ++- .../src/ast_mutate/move_expression_to_file.rs | 81 +++++---- .../src/ast_mutate/set_style_declarations.rs | 6 +- .../src/ast_mutate/set_style_mixins.rs | 6 +- libs/proto_ext/src/ast_mutate/test.rs | 165 ++++++++++++++++++ .../src/ast_mutate/toggle_instance_variant.rs | 3 +- 27 files changed, 375 insertions(+), 169 deletions(-) create mode 100644 libs/proto/src/ast/shared.proto create mode 100644 libs/proto/src/ast/shared.rs delete mode 100644 libs/proto_ext/src/ast/get_expr.rs create mode 100644 libs/proto_ext/src/ast_mutate/add_import.rs diff --git a/libs/ast_serialize/src/pc.rs b/libs/ast_serialize/src/pc.rs index 40c2dc7c0..4fd89d559 100644 --- a/libs/ast_serialize/src/pc.rs +++ b/libs/ast_serialize/src/pc.rs @@ -1,9 +1,9 @@ use crate::css::{serialize_decl_value, serialize_declarations}; use crate::docco::serialize_comment as serialize_doc_comment; use paperclip_common::serialize_context::Context; -use paperclip_proto::ast::base as base_ast; use paperclip_proto::ast::docco as docco_ast; use paperclip_proto::ast::pc as ast; +use paperclip_proto::ast::{base as base_ast, shared}; pub fn serialize(document: &ast::Document) -> String { let mut context = Context::new(0); @@ -322,7 +322,7 @@ pub fn serialize_string(node: &base_ast::Str, context: &mut Context) { } pub fn serialize_number(_node: &base_ast::Num, _context: &mut Context) {} -pub fn serialize_reference(node: &ast::Reference, context: &mut Context) { +pub fn serialize_reference(node: &shared::Reference, context: &mut Context) { context.add_buffer(node.path.join(".").as_str()); } diff --git a/libs/compiler-react/src/code_compiler.rs b/libs/compiler-react/src/code_compiler.rs index d9eb2cac3..666acc0bc 100644 --- a/libs/compiler-react/src/code_compiler.rs +++ b/libs/compiler-react/src/code_compiler.rs @@ -5,6 +5,7 @@ use paperclip_evaluator::core::utils::get_style_namespace; use paperclip_proto::ast::{ graph_ext::{Dependency, Graph}, pc as ast, + shared::Reference, }; use std::collections::BTreeMap; @@ -375,7 +376,7 @@ fn compile_simple_expression(expr: &ast::SimpleExpression, context: &mut Context } } -fn compile_reference(expr: &ast::Reference, context: &mut Context) { +fn compile_reference(expr: &Reference, context: &mut Context) { let mut parts = expr.path.iter().peekable(); while let Some(part) = parts.next() { diff --git a/libs/evaluator/src/css/evaluator.rs b/libs/evaluator/src/css/evaluator.rs index ecc6cc1b9..16734d4b7 100644 --- a/libs/evaluator/src/css/evaluator.rs +++ b/libs/evaluator/src/css/evaluator.rs @@ -10,6 +10,7 @@ use paperclip_proto::ast::graph_ext::{self as graph}; use paperclip_proto::ast::graph_ext::{self as graph_ref, Expr}; use paperclip_proto::ast::pc::override_body_item; use paperclip_proto::ast::pc::{self as ast}; +use paperclip_proto::ast::shared::Reference; use paperclip_proto::virt::css::Rule; use std::string::ToString; @@ -391,7 +392,7 @@ fn get_render_node_ns(context: &DocumentContext) -> Option( style: &ast::Style, - variant_refs: &Vec, + variant_refs: &Vec, expanded_combo_selectors: &Vec>, context: &mut DocumentContext, ) { @@ -714,7 +715,7 @@ fn get_combo_selectors2( // [[or, or, or] and [or]] fn collect_style_variant_selectors( - variant_refs: &Vec, + variant_refs: &Vec, context: &mut DocumentContext, ) -> Vec> { let mut combo_triggers = vec![]; diff --git a/libs/parser/src/css/parser.rs b/libs/parser/src/css/parser.rs index 259a9eda1..2352c7d5d 100644 --- a/libs/parser/src/css/parser.rs +++ b/libs/parser/src/css/parser.rs @@ -7,6 +7,7 @@ use crate::core::parser_context::Context; use crate::core::string_scanner::StringScanner; use paperclip_common::id::IDGenerator; use paperclip_proto::ast::css as ast; +use paperclip_proto::ast::shared as shared_ast; use std::str; type ParserContext<'tokenizer, 'scanner, 'idgenerator, 'src> = @@ -239,7 +240,7 @@ fn parse_call(context: &mut ParserContext) -> Result Result { +fn parse_reference(context: &mut ParserContext) -> Result { let start = context.curr_u16pos.clone(); let mut path: Vec = vec![]; @@ -255,7 +256,7 @@ fn parse_reference(context: &mut ParserContext) -> Result Result Result, err::ParserError> { +fn parse_style_extends( + context: &mut PCContext, +) -> Result, err::ParserError> { context.next_token()?; // eat context.skip(is_superfluous_or_newline)?; - let mut extends: Vec = vec![]; + let mut extends: Vec = vec![]; loop { extends.push(parse_ref(context)?); context.skip(is_superfluous_or_newline)?; @@ -833,11 +836,11 @@ fn parse_boolean(context: &mut PCContext) -> Result Result { +fn parse_ref(context: &mut PCContext) -> Result { let start = context.curr_u16pos.clone(); let path: Vec = parse_path(context)?; let end = context.curr_u16pos.clone(); - Ok(ast::Reference { + Ok(shared_ast::Reference { id: context.next_id(), range: Some(base_ast::Range::new(start, end)), path, diff --git a/libs/proto/build.rs b/libs/proto/build.rs index 20dcefbd2..4464a7c64 100644 --- a/libs/proto/build.rs +++ b/libs/proto/build.rs @@ -9,6 +9,7 @@ fn main() -> Result<(), Box> { "src/service/designer.proto", "src/ast/css.proto", "src/ast/base.proto", + "src/ast/shared.proto", "src/ast/graph.proto", "src/ast/pc.proto", "src/ast/docco.proto", diff --git a/libs/proto/src/ast/all/mod.rs b/libs/proto/src/ast/all/mod.rs index 669e21c6b..6c3379bbe 100644 --- a/libs/proto/src/ast/all/mod.rs +++ b/libs/proto/src/ast/all/mod.rs @@ -1,6 +1,7 @@ pub use super::base; pub use super::docco; pub use super::pc; +pub use super::shared; use crc::{Crc, CRC_32_ISCSI}; pub mod visit; @@ -193,7 +194,7 @@ expressions! { pc::simple_expression::Inner::Reference, pc::simple_expression::Inner::Ary )), - (Reference, pc::Reference, self => &self.id), + (Reference, shared::Reference, self => &self.id), (Ary, pc::Ary, self => &self.id), (Element, pc::Element, self => &self.id), (Node, pc::Node, self => &self.get_inner().get_id()), diff --git a/libs/proto/src/ast/all/visit.rs b/libs/proto/src/ast/all/visit.rs index 689cd8dd1..b9c82d70d 100644 --- a/libs/proto/src/ast/all/visit.rs +++ b/libs/proto/src/ast/all/visit.rs @@ -3,6 +3,7 @@ pub use super::super::css; pub use super::super::docco; pub use super::super::graph; pub use super::super::pc; +pub use super::super::shared; macro_rules! visitable { ( @@ -230,11 +231,6 @@ visitable! { css::declaration_value::Inner::CommaList ) }), - (css::Reference, visit_css_reference, (self, visitor) { - VisitorResult::Continue - },{ - VisitorResult::Continue - }), (css::Measurement, visit_css_measurement, (self, visitor) { VisitorResult::Continue },{ @@ -412,7 +408,7 @@ visit_enum!(self.get_inner_mut(), visitor, pc::trigger_body_item::Inner::Str, pc }, { visit_each!(&mut self.items, visitor) }), - (pc::Reference, visit_reference, (self, visitor) { + (shared::Reference, visit_reference, (self, visitor) { VisitorResult::Continue }, { VisitorResult::Continue diff --git a/libs/proto/src/ast/css.proto b/libs/proto/src/ast/css.proto index e611c6281..1bcd51cb0 100644 --- a/libs/proto/src/ast/css.proto +++ b/libs/proto/src/ast/css.proto @@ -1,5 +1,6 @@ syntax = "proto3"; import "ast/base.proto"; +import "ast/shared.proto"; package ast.css; @@ -14,7 +15,7 @@ message StyleDeclaration { message DeclarationValue { oneof inner { ast.base.Num number = 1; - Reference reference = 2; + ast.shared.Reference reference = 2; ast.base.Str str = 3; Measurement measurement = 4; FunctionCall function_call = 5; @@ -25,12 +26,6 @@ message DeclarationValue { } } -message Reference { - string id = 1; - ast.base.Range range = 2; - repeated string path = 3; -} - message Arithmetic { string id = 1; ast.base.Range range = 2; @@ -69,4 +64,4 @@ message CommaList { string id = 1; ast.base.Range range = 2; repeated DeclarationValue items = 3; -} \ No newline at end of file +} diff --git a/libs/proto/src/ast/get_expr.rs b/libs/proto/src/ast/get_expr.rs index 490fc132d..5a89f042b 100644 --- a/libs/proto/src/ast/get_expr.rs +++ b/libs/proto/src/ast/get_expr.rs @@ -1,6 +1,7 @@ use super::graph_ext::{Dependency, Graph}; use super::pc; -use super::pc::{document_body_item, DocumentBodyItem, Element}; +use super::pc::{document_body_item, DocumentBodyItem}; +use super::shared; use super::{all::ExpressionWrapper, pc::Component}; // use crate::ast::all::Visitable; @@ -34,6 +35,7 @@ impl<'expr> Visitor<()> for GetExpr { (visit_text_node, pc::TextNode), (visit_variant, pc::Variant), (visit_style, pc::Style), + (visit_reference, shared::Reference), (visit_atom, pc::Atom) } } diff --git a/libs/proto/src/ast/mod.rs b/libs/proto/src/ast/mod.rs index 08004de0d..837256574 100644 --- a/libs/proto/src/ast/mod.rs +++ b/libs/proto/src/ast/mod.rs @@ -6,3 +6,4 @@ pub mod get_expr; pub mod graph; pub mod graph_ext; pub mod pc; +pub mod shared; diff --git a/libs/proto/src/ast/pc.proto b/libs/proto/src/ast/pc.proto index 1428f193c..263196469 100644 --- a/libs/proto/src/ast/pc.proto +++ b/libs/proto/src/ast/pc.proto @@ -2,6 +2,7 @@ syntax = "proto3"; import "ast/base.proto"; import "ast/css.proto"; import "ast/docco.proto"; +import "ast/shared.proto"; package ast.pc; @@ -35,8 +36,8 @@ message Style { string id = 1; bool is_public = 2; optional string name = 3; - repeated Reference variant_combo = 4; - repeated Reference extends = 5; + repeated ast.shared.Reference variant_combo = 4; + repeated ast.shared.Reference extends = 5; ast.base.Range range = 6; repeated ast.css.StyleDeclaration declarations = 7; } @@ -113,7 +114,7 @@ message TriggerBodyItemCombo { message TriggerBodyItem { oneof inner { ast.base.Str str = 1; - Reference reference = 2; + ast.shared.Reference reference = 2; ast.base.Bool bool = 3; } } @@ -139,16 +140,11 @@ message SimpleExpression { ast.base.Str str = 1; ast.base.Num num = 2; ast.base.Bool bool = 3; - Reference reference = 4; + ast.shared.Reference reference = 4; Ary ary = 5; } } -message Reference { - string id = 1; - ast.base.Range range = 2; - repeated string path = 3; -} message Ary { string id = 1; diff --git a/libs/proto/src/ast/pc.rs b/libs/proto/src/ast/pc.rs index 80a0c3eca..d77393ede 100644 --- a/libs/proto/src/ast/pc.rs +++ b/libs/proto/src/ast/pc.rs @@ -1,6 +1,7 @@ use crate::add_inner_wrapper; use super::{ + all::ExpressionWrapper, get_expr::GetExpr, graph::{Dependency, Graph}, }; @@ -53,6 +54,31 @@ impl Document { pub fn get_import_by_src(&self, src: &str) -> Option<&Import> { self.get_imports().into_iter().find(|imp| &imp.path == src) } + pub fn get_export(&self, name: &str) -> Option { + for child in &self.body { + match child.get_inner() { + document_body_item::Inner::Component(component) => { + if component.name == name { + return Some(component.into()); + } + } + document_body_item::Inner::Style(style) => { + if let Some(style_name) = &style.name { + if style_name == name { + return Some(style.into()); + } + } + } + document_body_item::Inner::Atom(atom) => { + if atom.name == name { + return Some(atom.into()); + } + } + _ => {} + } + } + None + } pub fn get_component_by_name(&self, name: &str) -> Option<&Component> { self.get_components() .into_iter() diff --git a/libs/proto/src/ast/shared.proto b/libs/proto/src/ast/shared.proto new file mode 100644 index 000000000..7b592e5d2 --- /dev/null +++ b/libs/proto/src/ast/shared.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +import "ast/base.proto"; + +package ast.shared; + +message Reference { + string id = 1; + ast.base.Range range = 2; + repeated string path = 3; +} diff --git a/libs/proto/src/ast/shared.rs b/libs/proto/src/ast/shared.rs new file mode 100644 index 000000000..2f3a98486 --- /dev/null +++ b/libs/proto/src/ast/shared.rs @@ -0,0 +1,39 @@ +use super::{ + all::ExpressionWrapper, + graph::{Dependency, Graph}, +}; + +include!(concat!(env!("OUT_DIR"), "/ast.shared.rs")); + +impl Reference { + /** + * Follows reference to source + */ + pub fn follow<'a>(&'a self, graph: &'a Graph) -> Option<(ExpressionWrapper, &'a Dependency)> { + let (_, ref_dep) = graph.get_expr_dep(&self.id).expect("Dependency must exist"); + + let source = if self.path.len() == 2 { + let namespace = self.path.get(0).expect("Namespace must exist"); + let name = self.path.get(1).expect("Name must exist"); + + if let Some(ref_dep) = ref_dep.resolve_import_from_ns(namespace, graph) { + Some((name.clone(), ref_dep)) + } else { + None + } + } else if self.path.len() == 1 { + let name = self.path.get(0).expect("Name must exist"); + Some((name.clone(), ref_dep)) + } else { + None + }; + + if let Some((name, dep)) = source { + dep.get_document() + .get_export(&name) + .and_then(|expr| Some((expr, dep))) + } else { + None + } + } +} diff --git a/libs/proto/src/ast_mutate/mod.proto b/libs/proto/src/ast_mutate/mod.proto index 7e0920004..4971b8b26 100644 --- a/libs/proto/src/ast_mutate/mod.proto +++ b/libs/proto/src/ast_mutate/mod.proto @@ -35,6 +35,7 @@ message Mutation { SetId set_id = 16; PasteExpression paste_expression = 21; MoveExpressionToFile move_expression_to_file = 26; + AddImport add_import = 27; // Instance ToggleInstanceVariant toggle_instance_variant = 13; @@ -51,6 +52,12 @@ message Mutation { } } + +message AddImport { + string ns = 1; + string path = 2; +} + message WrapInElement { string target_id = 1; } diff --git a/libs/proto_ext/scripts/build.sh b/libs/proto_ext/scripts/build.sh index c3af8dbd4..11ed63083 100755 --- a/libs/proto_ext/scripts/build.sh +++ b/libs/proto_ext/scripts/build.sh @@ -1,4 +1,4 @@ #!/bin/sh # cd ..; # echo $(pwd); -# mkdir -p lib && protoc --proto_path=src --plugin=\"protoc-gen-grpc-web=../../node_modules/.bin/protoc-gen-grpc-web\" --grpc-web_out=\"import_style=commonjs+dts,mode=grpcwebtext:./lib\" --js_out=\"import_style=commonjs:./lib\" src/service/designer.proto src/ast/pc.proto src/ast/css.proto src/virt/core.proto src/virt/html.proto src/ast/base.proto src/virt/css.proto src/ast/docco.proto \ No newline at end of file +# mkdir -p lib && protoc --proto_path=src --plugin=\"protoc-gen-grpc-web=../../node_modules/.bin/protoc-gen-grpc-web\" --grpc-web_out=\"import_style=commonjs+dts,mode=grpcwebtext:./lib\" --js_out=\"import_style=commonjs:./lib\" src/service/designer.proto src/ast/pc.proto src/ast/css.proto src/virt/core.proto src/virt/html.proto src/ast/base.proto src/ast/shared.proto src/virt/css.proto src/ast/docco.proto diff --git a/libs/proto_ext/src/ast/get_expr.rs b/libs/proto_ext/src/ast/get_expr.rs deleted file mode 100644 index 4661bf992..000000000 --- a/libs/proto_ext/src/ast/get_expr.rs +++ /dev/null @@ -1,85 +0,0 @@ -use paperclip_proto::ast; -use paperclip_proto::ast::all::visit::{Visitable, Visitor, VisitorResult}; -use paperclip_proto::ast::graph_ext::{Dependency, Graph}; -use paperclip_proto::ast::pc::{document_body_item, DocumentBodyItem, Element}; -use paperclip_proto::ast::{all::ExpressionWrapper, pc::Component}; - -pub struct GetExpr { - id: String, - reference: Option, -} - -macro_rules! getters { - ($(($name: ident, $expr: ty)), *) => { - $( - fn $name(&mut self, expr: &$expr) -> VisitorResult<()> { - if expr.id == self.id { - self.reference = Some(expr.into()); - return VisitorResult::Return(()); - } - VisitorResult::Continue - } - )* - }; -} - -impl<'expr> Visitor<()> for GetExpr { - getters! { - (visit_element, ast::pc::Element), - (visit_component, ast::pc::Component), - (visit_text_node, ast::pc::TextNode), - (visit_variant, ast::pc::Variant), - (visit_style, ast::pc::Style), - (visit_atom, ast::pc::Atom) - } -} - -impl<'expr> GetExpr { - pub fn get_expr_from_graph<'graph>( - id: &str, - graph: &'graph Graph, - ) -> Option<(ExpressionWrapper, &'graph Dependency)> { - for (_path, dep) in &graph.dependencies { - if let Some(document) = &dep.document { - if let Some(reference) = GetExpr::get_expr(id, document) { - return Some((reference.clone(), &dep)); - } - } - } - - None - } - pub fn get_expr(id: &str, doc: &ast::pc::Document) -> Option { - let mut imp = GetExpr { - id: id.to_string(), - reference: None, - }; - doc.accept(&mut imp); - imp.reference.clone() - } - pub fn get_owner_component( - id: &str, - doc: &'expr ast::pc::Document, - ) -> Option<&'expr Component> { - let mut imp = GetExpr { - id: id.to_string(), - reference: None, - }; - - let mut found: Option<&DocumentBodyItem> = None; - for item in &doc.body { - if matches!(item.accept(&mut imp), VisitorResult::Return(_)) { - found = Some(item); - break; - } - } - - found.and_then(|item| { - if let document_body_item::Inner::Component(component) = item.get_inner() { - Some(component) - } else { - None - } - }) - } -} diff --git a/libs/proto_ext/src/ast/mod.rs b/libs/proto_ext/src/ast/mod.rs index 40c06a3e4..24dc72cdc 100644 --- a/libs/proto_ext/src/ast/mod.rs +++ b/libs/proto_ext/src/ast/mod.rs @@ -1,2 +1 @@ -// pub mod get_expr; pub mod pc; diff --git a/libs/proto_ext/src/ast_mutate/add_import.rs b/libs/proto_ext/src/ast_mutate/add_import.rs new file mode 100644 index 000000000..49e729cdf --- /dev/null +++ b/libs/proto_ext/src/ast_mutate/add_import.rs @@ -0,0 +1,15 @@ +use crate::ast_mutate::utils::import_dep; + +use super::base::EditContext; +use paperclip_proto::{ast::pc::Document, ast_mutate::AddImport}; + +use paperclip_proto::ast::all::visit::{MutableVisitor, VisitorResult}; + +impl MutableVisitor<()> for EditContext { + fn visit_document(&mut self, doc: &mut Document) -> VisitorResult<()> { + println!("DO IT!"); + import_dep(doc, &self.mutation.path, self); + + VisitorResult::Return(()) + } +} diff --git a/libs/proto_ext/src/ast_mutate/base.rs b/libs/proto_ext/src/ast_mutate/base.rs index 95294c380..f02df4e90 100644 --- a/libs/proto_ext/src/ast_mutate/base.rs +++ b/libs/proto_ext/src/ast_mutate/base.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use paperclip_common::id::IDGenerator; use paperclip_proto::ast::all::Expression; +use paperclip_proto::ast_mutate::{self}; use paperclip_proto::{ ast::{graph::Dependency, graph_ext::Graph}, ast_mutate::MutationResult, @@ -13,6 +14,7 @@ pub struct EditContext { pub path: String, pub graph: Rc, pub changes: Rc>>, + pub post_mutations: Rc>>, } impl<'a, Mutation> EditContext { @@ -35,8 +37,12 @@ impl<'a, Mutation> EditContext { path: self.path.clone(), graph: self.graph.clone(), changes: self.changes.clone(), + post_mutations: self.post_mutations.clone(), } } + pub fn add_post_mutation(&mut self, mutation: ast_mutate::Mutation) { + self.post_mutations.borrow_mut().push(mutation); + } pub fn new(mutation: Mutation, path: &str, graph: Rc) -> EditContext { let dep: &Dependency = graph .dependencies @@ -51,6 +57,7 @@ impl<'a, Mutation> EditContext { Self { mutation, + post_mutations: Rc::new(RefCell::new(vec![])), id_generator: Rc::new(RefCell::new(IDGenerator::new(checksum))), path: path.to_string(), graph: graph.clone(), diff --git a/libs/proto_ext/src/ast_mutate/mod.rs b/libs/proto_ext/src/ast_mutate/mod.rs index 4e90845d7..c1b755373 100644 --- a/libs/proto_ext/src/ast_mutate/mod.rs +++ b/libs/proto_ext/src/ast_mutate/mod.rs @@ -1,3 +1,4 @@ +mod add_import; mod append_child; mod append_insert; mod base; @@ -27,6 +28,7 @@ mod utils; use std::{collections::HashMap, rc::Rc}; use crate::graph::{get_document_imports, io::IO}; +pub use add_import::*; use anyhow::Result; pub use append_child::*; pub use append_insert::*; @@ -89,15 +91,21 @@ pub fn edit_graph( for mutation in mutations { for (path, dep) in &mut graph.dependencies { - let mut ctx = EditContext::new(mutation.clone(), &dep.path, ctx_graph.clone()); - dep.accept(&mut ctx); - let doc = dep.document.as_ref().expect("Document must exist"); + let mut mutations = vec![mutation.clone()]; - dep.imports = get_document_imports(doc, &dep.path, io)?; + while !mutations.is_empty() { + let mutation = mutations.remove(0); + let mut ctx = EditContext::new(mutation.clone(), &dep.path, ctx_graph.clone()); + dep.accept(&mut ctx); + if ctx.changes.borrow().len() > 0 { + changed.push((path.to_string(), ctx.changes.borrow().clone().to_vec())); + } - if ctx.changes.borrow().len() > 0 { - changed.push((path.to_string(), ctx.changes.borrow().clone().to_vec())); + mutations.extend(ctx.post_mutations.borrow().clone()); } + + let doc = dep.document.as_ref().expect("Document must exist"); + dep.imports = get_document_imports(doc, &dep.path, io)?; } } @@ -119,6 +127,7 @@ mutations! { UpdateDependencyPath, UpdateVariant, MoveExpressionToFile, + AddImport, AppendInsert, SetTagName, PrependChild, diff --git a/libs/proto_ext/src/ast_mutate/move_expression_to_file.rs b/libs/proto_ext/src/ast_mutate/move_expression_to_file.rs index e743e1cb8..7b776a211 100644 --- a/libs/proto_ext/src/ast_mutate/move_expression_to_file.rs +++ b/libs/proto_ext/src/ast_mutate/move_expression_to_file.rs @@ -1,15 +1,16 @@ use crate::ast_mutate::utils::resolve_import_ns; -use super::{base::EditContext, utils::import_dep}; +use super::base::EditContext; use paperclip_common::get_or_short; use paperclip_proto::{ - ast::css::FunctionCall, + ast::css, ast::pc::Element, ast::{ all::{Expression, ExpressionWrapper}, - pc::{document_body_item, Document, Style}, + pc::{document_body_item, Document}, + shared::Reference, }, - ast_mutate::MoveExpressionToFile, + ast_mutate::{mutation, AddImport, MoveExpressionToFile}, }; use paperclip_proto::ast::all::visit::{MutableVisitor, VisitorResult}; @@ -26,18 +27,18 @@ impl MutableVisitor<()> for EditContext { ExpressionWrapper::Component(expr) => { Some(document_body_item::Inner::Component(expr.clone()).get_outer()) } - // ExpressionWrapper::Style(expr) => { - - // }, - // ExpressionWrapper::TextNode(expr) => { - - // }, - // ExpressionWrapper::Element(expr) => { - - // }, - // ExpressionWrapper::Atom(expr) => { - // Some(document_body_item::Inner::Atom(expr.clone()).get_outer()) - // }, + ExpressionWrapper::Style(expr) => { + Some(document_body_item::Inner::Style(expr.clone()).get_outer()) + } + ExpressionWrapper::TextNode(expr) => { + Some(document_body_item::Inner::Text(expr.clone()).get_outer()) + } + ExpressionWrapper::Element(expr) => { + Some(document_body_item::Inner::Element(expr.clone()).get_outer()) + } + ExpressionWrapper::Atom(expr) => { + Some(document_body_item::Inner::Atom(expr.clone()).get_outer()) + } _ => None, }; @@ -55,18 +56,6 @@ impl MutableVisitor<()> for EditContext { } VisitorResult::Continue } else { - let resolved = self - .get_dependency() - .imports - .iter() - .find(|(_key, value)| value == &&expr_dep.path); - - if resolved.is_none() { - return VisitorResult::Continue; - } - - import_dep(doc, &self.mutation.new_file_path, self); - VisitorResult::Continue } } @@ -86,21 +75,47 @@ impl MutableVisitor<()> for EditContext { if component.name == el.tag_name && el_dep.path == expr_dep.path { let (new_ns, _) = resolve_import_ns(&self.get_dependency(), &self.mutation.new_file_path); - el.namespace = Some(new_ns); + el.namespace = Some(new_ns.clone()); + + self.add_post_mutation( + mutation::Inner::AddImport(AddImport { + ns: new_ns.clone(), + path: self.mutation.new_file_path.clone(), + }) + .get_outer(), + ); } } VisitorResult::Continue } - fn visit_style(&mut self, style: &mut Style) -> VisitorResult<()> { - for extends in &style.extends {} - + fn visit_reference(&mut self, reference: &mut Reference) -> VisitorResult<()> { + if let Some((expr, _dep)) = reference.follow(&self.graph) { + if expr.get_id() == &self.mutation.expression_id { + let (ns, _) = + resolve_import_ns(self.get_dependency(), &self.mutation.new_file_path); + + self.add_post_mutation( + mutation::Inner::AddImport(AddImport { + ns: ns.clone(), + path: self.mutation.new_file_path.clone(), + }) + .get_outer(), + ); + + if reference.path.len() == 2 { + let _ = std::mem::replace(&mut reference.path[0], ns); + } else if reference.path.len() == 1 { + reference.path.insert(0, ns); + } + } + } VisitorResult::Continue } // check for tokens - fn visit_css_function_call(&mut self, _expr: &mut Box) -> VisitorResult<()> { + fn visit_css_function_call(&mut self, _expr: &mut Box) -> VisitorResult<()> { VisitorResult::Continue } } diff --git a/libs/proto_ext/src/ast_mutate/set_style_declarations.rs b/libs/proto_ext/src/ast_mutate/set_style_declarations.rs index 8461f3b92..7dfc46de4 100644 --- a/libs/proto_ext/src/ast_mutate/set_style_declarations.rs +++ b/libs/proto_ext/src/ast_mutate/set_style_declarations.rs @@ -129,12 +129,12 @@ fn add_child_style( new_style.variant_combo = variant_names .iter() - .map(|name| ast::pc::Reference { + .map(|name| ast::shared::Reference { id: ctx.new_id(), path: vec![name.to_string()], range: None, }) - .collect::>(); + .collect::>(); let mut found = false; @@ -161,7 +161,7 @@ fn add_child_style( VisitorResult::Continue } -fn variant_combo_equals(a: &Vec, b: &Vec) -> bool { +fn variant_combo_equals(a: &Vec, b: &Vec) -> bool { if a.len() != b.len() { return false; } diff --git a/libs/proto_ext/src/ast_mutate/set_style_mixins.rs b/libs/proto_ext/src/ast_mutate/set_style_mixins.rs index b8f40f584..9905dc83f 100644 --- a/libs/proto_ext/src/ast_mutate/set_style_mixins.rs +++ b/libs/proto_ext/src/ast_mutate/set_style_mixins.rs @@ -4,7 +4,7 @@ use super::utils::resolve_import_ns; use paperclip_proto::ast; use paperclip_proto::ast::all::visit::MutableVisitor; use paperclip_proto::ast::all::visit::VisitorResult; -use paperclip_proto::ast::pc::Reference; +use paperclip_proto::ast::shared::Reference; use paperclip_proto::ast_mutate::SetStyleMixins; use paperclip_proto::ast::get_expr::GetExpr; @@ -63,12 +63,12 @@ impl MutableVisitor<()> for EditContext { declarations: vec![], variant_combo: variant_combo .iter() - .map(|x| ast::pc::Reference { + .map(|x| ast::shared::Reference { id: self.new_id(), path: vec![x.clone()], range: None, }) - .collect::>(), + .collect::>(), name: None, extends: vec![], }) diff --git a/libs/proto_ext/src/ast_mutate/test.rs b/libs/proto_ext/src/ast_mutate/test.rs index ca90f6be6..f4dc55dbe 100644 --- a/libs/proto_ext/src/ast_mutate/test.rs +++ b/libs/proto_ext/src/ast_mutate/test.rs @@ -32,6 +32,8 @@ macro_rules! case { panic!("Unable to load"); } + println!("{:#?}", graph.dependencies); + edit_graph(&mut graph, &vec![$edit], &mock_fs).expect("Can't edit graph"); let edited_docs = graph @@ -4312,3 +4314,166 @@ case! { "# )] } + +case! { + refs_are_updated_when_atom_is_moved, + [ + ( + "/entry.pc", r#" + import "/a.pc" as mod + + div { + style { + background: var(mod.blue) + } + } + "# + ), + ( + "/a.pc", r#" + public token blue #0000FF + "# + ), + + ( + "/b.pc", r#" + "# + ) + ], + mutation::Inner::MoveExpressionToFile(MoveExpressionToFile { + expression_id: "98523c41-2".to_string(), + new_file_path: "/b.pc".to_string() + }).get_outer(), + [( + "/entry.pc", r#" + import "./b.pc" as module + import "/a.pc" as mod + + div { + style { + background: var(module.blue) + } + } + "# + ), + ( + "/a.pc", r#" + "# + ), + ( + "/b.pc", r#" + public token blue #0000FF + "# + )] +} + +case! { + refs_are_update_when_atom_moved_out_of_dep_where_its_used, + [ + ( + "/entry.pc", r#" + public token blue #0000FF + + div { + style { + background: var(blue) + } + } + "# + ), + ( + "/a.pc", r#" + "# + ) + ], + mutation::Inner::MoveExpressionToFile(MoveExpressionToFile { + expression_id: "80f4925f-2".to_string(), + new_file_path: "/a.pc".to_string() + }).get_outer(), + [( + "/entry.pc", r#" + import "./a.pc" as module + + div { + style { + background: var(module.blue) + } + } + "# + ), + ( + "/a.pc", r#" + public token blue #0000FF + "# + )] +} + +case! { + can_move_an_element_to_a_doc, + [ + ( + "/entry.pc", r#" + + + div { + style { + background: var(blue) + } + } + "# + ), + ( + "/a.pc", r#" + "# + ) + ], + mutation::Inner::MoveExpressionToFile(MoveExpressionToFile { + expression_id: "80f4925f-5".to_string(), + new_file_path: "/a.pc".to_string() + }).get_outer(), + [( + "/entry.pc", r#" + "# + ), + ( + "/a.pc", r#" + + div { + style { + background: var(blue) + } + } + "# + )] +} + +case! { + can_move_a_text_node_to_a_doc, + [ + ( + "/entry.pc", r#" + + + text "ab" + "# + ), + ( + "/a.pc", r#" + "# + ) + ], + mutation::Inner::MoveExpressionToFile(MoveExpressionToFile { + expression_id: "80f4925f-1".to_string(), + new_file_path: "/a.pc".to_string() + }).get_outer(), + [( + "/entry.pc", r#" + "# + ), + ( + "/a.pc", r#" + + text "ab" + "# + )] +} diff --git a/libs/proto_ext/src/ast_mutate/toggle_instance_variant.rs b/libs/proto_ext/src/ast_mutate/toggle_instance_variant.rs index 027cd178f..9b76b8a96 100644 --- a/libs/proto_ext/src/ast_mutate/toggle_instance_variant.rs +++ b/libs/proto_ext/src/ast_mutate/toggle_instance_variant.rs @@ -2,7 +2,8 @@ use super::base::EditContext; use paperclip_common::get_or_short; use paperclip_proto::ast; use paperclip_proto::ast::all::visit::{MutableVisitor, VisitorResult}; -use paperclip_proto::ast::pc::{Reference, Variant}; +use paperclip_proto::ast::pc::Variant; +use paperclip_proto::ast::shared::Reference; use paperclip_proto::ast_mutate::ToggleInstanceVariant; use paperclip_proto::ast::get_expr::GetExpr;