aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax/src/ast')
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs129
-rw-r--r--crates/syntax/src/ast/generated/nodes.rs10
-rw-r--r--crates/syntax/src/ast/make.rs14
-rw-r--r--crates/syntax/src/ast/node_ext.rs4
4 files changed, 152 insertions, 5 deletions
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
new file mode 100644
index 000000000..449b058fb
--- /dev/null
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -0,0 +1,129 @@
1//! Structural editing for ast.
2
3use std::iter::empty;
4
5use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
6use parser::T;
7
8use crate::{
9 ast,
10 ted::{self, Position},
11 AstNode, Direction, SyntaxElement,
12};
13
14use super::NameOwner;
15
16pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner + AstNodeEdit {
17 fn get_or_create_where_clause(&self) -> ast::WhereClause;
18}
19
20impl GenericParamsOwnerEdit for ast::Fn {
21 fn get_or_create_where_clause(&self) -> WhereClause {
22 if self.where_clause().is_none() {
23 let position = if let Some(ty) = self.ret_type() {
24 Position::after(ty.syntax().clone())
25 } else if let Some(param_list) = self.param_list() {
26 Position::after(param_list.syntax().clone())
27 } else {
28 Position::last_child_of(self.syntax().clone())
29 };
30 create_where_clause(position)
31 }
32 self.where_clause().unwrap()
33 }
34}
35
36impl GenericParamsOwnerEdit for ast::Impl {
37 fn get_or_create_where_clause(&self) -> WhereClause {
38 if self.where_clause().is_none() {
39 let position = if let Some(items) = self.assoc_item_list() {
40 Position::before(items.syntax().clone())
41 } else {
42 Position::last_child_of(self.syntax().clone())
43 };
44 create_where_clause(position)
45 }
46 self.where_clause().unwrap()
47 }
48}
49
50impl GenericParamsOwnerEdit for ast::Trait {
51 fn get_or_create_where_clause(&self) -> WhereClause {
52 if self.where_clause().is_none() {
53 let position = if let Some(items) = self.assoc_item_list() {
54 Position::before(items.syntax().clone())
55 } else {
56 Position::last_child_of(self.syntax().clone())
57 };
58 create_where_clause(position)
59 }
60 self.where_clause().unwrap()
61 }
62}
63
64impl GenericParamsOwnerEdit for ast::Struct {
65 fn get_or_create_where_clause(&self) -> WhereClause {
66 if self.where_clause().is_none() {
67 let tfl = self.field_list().and_then(|fl| match fl {
68 ast::FieldList::RecordFieldList(_) => None,
69 ast::FieldList::TupleFieldList(it) => Some(it),
70 });
71 let position = if let Some(tfl) = tfl {
72 Position::after(tfl.syntax().clone())
73 } else if let Some(gpl) = self.generic_param_list() {
74 Position::after(gpl.syntax().clone())
75 } else if let Some(name) = self.name() {
76 Position::after(name.syntax().clone())
77 } else {
78 Position::last_child_of(self.syntax().clone())
79 };
80 create_where_clause(position)
81 }
82 self.where_clause().unwrap()
83 }
84}
85
86impl GenericParamsOwnerEdit for ast::Enum {
87 fn get_or_create_where_clause(&self) -> WhereClause {
88 if self.where_clause().is_none() {
89 let position = if let Some(gpl) = self.generic_param_list() {
90 Position::after(gpl.syntax().clone())
91 } else if let Some(name) = self.name() {
92 Position::after(name.syntax().clone())
93 } else {
94 Position::last_child_of(self.syntax().clone())
95 };
96 create_where_clause(position)
97 }
98 self.where_clause().unwrap()
99 }
100}
101
102fn create_where_clause(position: Position) {
103 let where_clause: SyntaxElement =
104 make::where_clause(empty()).clone_for_update().syntax().clone().into();
105 ted::insert(position, where_clause);
106}
107
108impl ast::WhereClause {
109 pub fn add_predicate(&self, predicate: ast::WherePred) {
110 if let Some(pred) = self.predicates().last() {
111 if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) {
112 ted::append_child_raw(self.syntax().clone(), make::token(T![,]));
113 }
114 }
115 ted::append_child(self.syntax().clone(), predicate.syntax().clone())
116 }
117}
118
119impl ast::TypeBoundList {
120 pub fn remove(&self) {
121 if let Some(colon) =
122 self.syntax().siblings_with_tokens(Direction::Prev).find(|it| it.kind() == T![:])
123 {
124 ted::remove_all(colon..=self.syntax().clone().into())
125 } else {
126 ted::remove(self.syntax().clone())
127 }
128 }
129}
diff --git a/crates/syntax/src/ast/generated/nodes.rs b/crates/syntax/src/ast/generated/nodes.rs
index 064931aec..6097178b6 100644
--- a/crates/syntax/src/ast/generated/nodes.rs
+++ b/crates/syntax/src/ast/generated/nodes.rs
@@ -1336,6 +1336,7 @@ pub enum Expr {
1336 Literal(Literal), 1336 Literal(Literal),
1337 LoopExpr(LoopExpr), 1337 LoopExpr(LoopExpr),
1338 MacroCall(MacroCall), 1338 MacroCall(MacroCall),
1339 MacroStmts(MacroStmts),
1339 MatchExpr(MatchExpr), 1340 MatchExpr(MatchExpr),
1340 MethodCallExpr(MethodCallExpr), 1341 MethodCallExpr(MethodCallExpr),
1341 ParenExpr(ParenExpr), 1342 ParenExpr(ParenExpr),
@@ -3034,6 +3035,9 @@ impl From<LoopExpr> for Expr {
3034impl From<MacroCall> for Expr { 3035impl From<MacroCall> for Expr {
3035 fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) } 3036 fn from(node: MacroCall) -> Expr { Expr::MacroCall(node) }
3036} 3037}
3038impl From<MacroStmts> for Expr {
3039 fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) }
3040}
3037impl From<MatchExpr> for Expr { 3041impl From<MatchExpr> for Expr {
3038 fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) } 3042 fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
3039} 3043}
@@ -3078,8 +3082,8 @@ impl AstNode for Expr {
3078 match kind { 3082 match kind {
3079 ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR 3083 ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
3080 | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR 3084 | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | EFFECT_EXPR | FIELD_EXPR | FOR_EXPR
3081 | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MATCH_EXPR 3085 | IF_EXPR | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_CALL | MACRO_STMTS
3082 | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR 3086 | MATCH_EXPR | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
3083 | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR 3087 | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
3084 | YIELD_EXPR => true, 3088 | YIELD_EXPR => true,
3085 _ => false, 3089 _ => false,
@@ -3105,6 +3109,7 @@ impl AstNode for Expr {
3105 LITERAL => Expr::Literal(Literal { syntax }), 3109 LITERAL => Expr::Literal(Literal { syntax }),
3106 LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }), 3110 LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
3107 MACRO_CALL => Expr::MacroCall(MacroCall { syntax }), 3111 MACRO_CALL => Expr::MacroCall(MacroCall { syntax }),
3112 MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
3108 MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }), 3113 MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
3109 METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }), 3114 METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
3110 PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }), 3115 PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
@@ -3142,6 +3147,7 @@ impl AstNode for Expr {
3142 Expr::Literal(it) => &it.syntax, 3147 Expr::Literal(it) => &it.syntax,
3143 Expr::LoopExpr(it) => &it.syntax, 3148 Expr::LoopExpr(it) => &it.syntax,
3144 Expr::MacroCall(it) => &it.syntax, 3149 Expr::MacroCall(it) => &it.syntax,
3150 Expr::MacroStmts(it) => &it.syntax,
3145 Expr::MatchExpr(it) => &it.syntax, 3151 Expr::MatchExpr(it) => &it.syntax,
3146 Expr::MethodCallExpr(it) => &it.syntax, 3152 Expr::MethodCallExpr(it) => &it.syntax,
3147 Expr::ParenExpr(it) => &it.syntax, 3153 Expr::ParenExpr(it) => &it.syntax,
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 05a6b0b25..810c8d4c8 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -174,6 +174,11 @@ pub fn block_expr(
174pub fn expr_unit() -> ast::Expr { 174pub fn expr_unit() -> ast::Expr {
175 expr_from_text("()") 175 expr_from_text("()")
176} 176}
177pub fn expr_literal(text: &str) -> ast::Literal {
178 assert_eq!(text.trim(), text);
179 ast_from_text(&format!("fn f() {{ let _ = {}; }}", text))
180}
181
177pub fn expr_empty_block() -> ast::Expr { 182pub fn expr_empty_block() -> ast::Expr {
178 expr_from_text("{}") 183 expr_from_text("{}")
179} 184}
@@ -390,6 +395,7 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken {
390 tokens::SOURCE_FILE 395 tokens::SOURCE_FILE
391 .tree() 396 .tree()
392 .syntax() 397 .syntax()
398 .clone_for_update()
393 .descendants_with_tokens() 399 .descendants_with_tokens()
394 .filter_map(|it| it.into_token()) 400 .filter_map(|it| it.into_token())
395 .find(|it| it.kind() == kind) 401 .find(|it| it.kind() == kind)
@@ -544,6 +550,7 @@ pub mod tokens {
544 SOURCE_FILE 550 SOURCE_FILE
545 .tree() 551 .tree()
546 .syntax() 552 .syntax()
553 .clone_for_update()
547 .descendants_with_tokens() 554 .descendants_with_tokens()
548 .filter_map(|it| it.into_token()) 555 .filter_map(|it| it.into_token())
549 .find(|it| it.kind() == WHITESPACE && it.text() == " ") 556 .find(|it| it.kind() == WHITESPACE && it.text() == " ")
@@ -569,13 +576,16 @@ pub mod tokens {
569 } 576 }
570 577
571 pub fn single_newline() -> SyntaxToken { 578 pub fn single_newline() -> SyntaxToken {
572 SOURCE_FILE 579 let res = SOURCE_FILE
573 .tree() 580 .tree()
574 .syntax() 581 .syntax()
582 .clone_for_update()
575 .descendants_with_tokens() 583 .descendants_with_tokens()
576 .filter_map(|it| it.into_token()) 584 .filter_map(|it| it.into_token())
577 .find(|it| it.kind() == WHITESPACE && it.text() == "\n") 585 .find(|it| it.kind() == WHITESPACE && it.text() == "\n")
578 .unwrap() 586 .unwrap();
587 res.detach();
588 res
579 } 589 }
580 590
581 pub fn blank_line() -> SyntaxToken { 591 pub fn blank_line() -> SyntaxToken {
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 52ac97c84..0b0d39a75 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -34,7 +34,9 @@ impl ast::NameRef {
34} 34}
35 35
36fn text_of_first_token(node: &SyntaxNode) -> &str { 36fn text_of_first_token(node: &SyntaxNode) -> &str {
37 node.green().children().next().and_then(|it| it.into_token()).unwrap().text() 37 let t =
38 node.green().children().next().and_then(|it| it.into_token()).unwrap().text().to_string();
39 Box::leak(Box::new(t))
38} 40}
39 41
40pub enum Macro { 42pub enum Macro {