From e010b144d5abcbd0947d0490123ef693a6a17c78 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 30 Sep 2019 09:27:26 +0300 Subject: move field list to ast/edit.rs --- crates/ra_syntax/src/ast/edit.rs | 82 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'crates/ra_syntax/src/ast/edit.rs') diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 2af6f573e..6e64c0675 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs @@ -12,7 +12,7 @@ use crate::{ make::{self, tokens}, AstNode, }, - AstToken, InsertPosition, SmolStr, SyntaxElement, + AstToken, Direction, InsertPosition, SmolStr, SyntaxElement, SyntaxKind::{ATTR, COMMENT, WHITESPACE}, SyntaxNode, T, }; @@ -105,6 +105,86 @@ impl ast::ItemList { } } +impl ast::RecordFieldList { + #[must_use] + pub fn append_field(&self, field: &ast::RecordField) -> ast::RecordFieldList { + self.insert_field(InsertPosition::Last, field) + } + + #[must_use] + pub fn insert_field( + &self, + position: InsertPosition<&'_ ast::RecordField>, + field: &ast::RecordField, + ) -> ast::RecordFieldList { + let is_multiline = self.syntax().text().contains_char('\n'); + let ws; + let space = if is_multiline { + ws = tokens::WsBuilder::new(&format!( + "\n{} ", + leading_indent(self.syntax()).unwrap_or("".into()) + )); + ws.ws() + } else { + tokens::single_space() + }; + + let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new(); + to_insert.push(space.into()); + to_insert.push(field.syntax().clone().into()); + to_insert.push(tokens::comma().into()); + + macro_rules! after_l_curly { + () => {{ + let anchor = match self.l_curly() { + Some(it) => it, + None => return self.clone(), + }; + InsertPosition::After(anchor) + }}; + } + + macro_rules! after_field { + ($anchor:expr) => { + if let Some(comma) = $anchor + .syntax() + .siblings_with_tokens(Direction::Next) + .find(|it| it.kind() == T![,]) + { + InsertPosition::After(comma) + } else { + to_insert.insert(0, tokens::comma().into()); + InsertPosition::After($anchor.syntax().clone().into()) + } + }; + }; + + let position = match position { + InsertPosition::First => after_l_curly!(), + InsertPosition::Last => { + if !is_multiline { + // don't insert comma before curly + to_insert.pop(); + } + match self.fields().last() { + Some(it) => after_field!(it), + None => after_l_curly!(), + } + } + InsertPosition::Before(anchor) => { + InsertPosition::Before(anchor.syntax().clone().into()) + } + InsertPosition::After(anchor) => after_field!(anchor), + }; + + insert_children(self, position, to_insert.iter().cloned()) + } + + fn l_curly(&self) -> Option { + self.syntax().children_with_tokens().find(|it| it.kind() == T!['{']) + } +} + pub fn strip_attrs_and_docs(node: N) -> N { N::cast(strip_attrs_and_docs_inner(node.syntax().clone())).unwrap() } -- cgit v1.2.3