aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/expr_extensions.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-04-02 10:47:39 +0100
committerAleksey Kladov <[email protected]>2019-04-02 10:47:39 +0100
commitcb5001c0a5ddadccd18fe787d89de3d6c3c8147f (patch)
tree1acf66538292bb3fc9e789ab1e55f61ee46b997e /crates/ra_syntax/src/ast/expr_extensions.rs
parentf3a82c372ccaa079842f151b749fbe9b8b9eb004 (diff)
move extensions to submodules
Diffstat (limited to 'crates/ra_syntax/src/ast/expr_extensions.rs')
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs250
1 files changed, 250 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
new file mode 100644
index 000000000..ddc26206f
--- /dev/null
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -0,0 +1,250 @@
1use crate::{
2 SyntaxToken, SyntaxElement, SmolStr,
3 ast::{self, AstNode, AstChildren, children, child_opt},
4 SyntaxKind::*
5};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum ElseBranch<'a> {
9 Block(&'a ast::Block),
10 IfExpr(&'a ast::IfExpr),
11}
12
13impl ast::IfExpr {
14 pub fn then_branch(&self) -> Option<&ast::Block> {
15 self.blocks().nth(0)
16 }
17 pub fn else_branch(&self) -> Option<ElseBranch> {
18 let res = match self.blocks().nth(1) {
19 Some(block) => ElseBranch::Block(block),
20 None => {
21 let elif: &ast::IfExpr = child_opt(self)?;
22 ElseBranch::IfExpr(elif)
23 }
24 };
25 Some(res)
26 }
27
28 fn blocks(&self) -> AstChildren<ast::Block> {
29 children(self)
30 }
31}
32
33impl ast::RefExpr {
34 pub fn is_mut(&self) -> bool {
35 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
36 }
37}
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
40pub enum PrefixOp {
41 /// The `*` operator for dereferencing
42 Deref,
43 /// The `!` operator for logical inversion
44 Not,
45 /// The `-` operator for negation
46 Neg,
47}
48
49impl ast::PrefixExpr {
50 pub fn op_kind(&self) -> Option<PrefixOp> {
51 match self.op_token()?.kind() {
52 STAR => Some(PrefixOp::Deref),
53 EXCL => Some(PrefixOp::Not),
54 MINUS => Some(PrefixOp::Neg),
55 _ => None,
56 }
57 }
58
59 pub fn op_token(&self) -> Option<SyntaxToken> {
60 self.syntax().first_child_or_token()?.as_token()
61 }
62}
63
64#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
65pub enum BinOp {
66 /// The `||` operator for boolean OR
67 BooleanOr,
68 /// The `&&` operator for boolean AND
69 BooleanAnd,
70 /// The `==` operator for equality testing
71 EqualityTest,
72 /// The `!=` operator for equality testing
73 NegatedEqualityTest,
74 /// The `<=` operator for lesser-equal testing
75 LesserEqualTest,
76 /// The `>=` operator for greater-equal testing
77 GreaterEqualTest,
78 /// The `<` operator for comparison
79 LesserTest,
80 /// The `>` operator for comparison
81 GreaterTest,
82 /// The `+` operator for addition
83 Addition,
84 /// The `*` operator for multiplication
85 Multiplication,
86 /// The `-` operator for subtraction
87 Subtraction,
88 /// The `/` operator for division
89 Division,
90 /// The `%` operator for remainder after division
91 Remainder,
92 /// The `<<` operator for left shift
93 LeftShift,
94 /// The `>>` operator for right shift
95 RightShift,
96 /// The `^` operator for bitwise XOR
97 BitwiseXor,
98 /// The `|` operator for bitwise OR
99 BitwiseOr,
100 /// The `&` operator for bitwise AND
101 BitwiseAnd,
102 /// The `..` operator for right-open ranges
103 RangeRightOpen,
104 /// The `..=` operator for right-closed ranges
105 RangeRightClosed,
106 /// The `=` operator for assignment
107 Assignment,
108 /// The `+=` operator for assignment after addition
109 AddAssign,
110 /// The `/=` operator for assignment after division
111 DivAssign,
112 /// The `*=` operator for assignment after multiplication
113 MulAssign,
114 /// The `%=` operator for assignment after remainders
115 RemAssign,
116 /// The `>>=` operator for assignment after shifting right
117 ShrAssign,
118 /// The `<<=` operator for assignment after shifting left
119 ShlAssign,
120 /// The `-=` operator for assignment after subtraction
121 SubAssign,
122 /// The `|=` operator for assignment after bitwise OR
123 BitOrAssign,
124 /// The `&=` operator for assignment after bitwise AND
125 BitAndAssign,
126 /// The `^=` operator for assignment after bitwise XOR
127 BitXorAssign,
128}
129
130impl ast::BinExpr {
131 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
132 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
133 match c.kind() {
134 PIPEPIPE => Some((c, BinOp::BooleanOr)),
135 AMPAMP => Some((c, BinOp::BooleanAnd)),
136 EQEQ => Some((c, BinOp::EqualityTest)),
137 NEQ => Some((c, BinOp::NegatedEqualityTest)),
138 LTEQ => Some((c, BinOp::LesserEqualTest)),
139 GTEQ => Some((c, BinOp::GreaterEqualTest)),
140 L_ANGLE => Some((c, BinOp::LesserTest)),
141 R_ANGLE => Some((c, BinOp::GreaterTest)),
142 PLUS => Some((c, BinOp::Addition)),
143 STAR => Some((c, BinOp::Multiplication)),
144 MINUS => Some((c, BinOp::Subtraction)),
145 SLASH => Some((c, BinOp::Division)),
146 PERCENT => Some((c, BinOp::Remainder)),
147 SHL => Some((c, BinOp::LeftShift)),
148 SHR => Some((c, BinOp::RightShift)),
149 CARET => Some((c, BinOp::BitwiseXor)),
150 PIPE => Some((c, BinOp::BitwiseOr)),
151 AMP => Some((c, BinOp::BitwiseAnd)),
152 DOTDOT => Some((c, BinOp::RangeRightOpen)),
153 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
154 EQ => Some((c, BinOp::Assignment)),
155 PLUSEQ => Some((c, BinOp::AddAssign)),
156 SLASHEQ => Some((c, BinOp::DivAssign)),
157 STAREQ => Some((c, BinOp::MulAssign)),
158 PERCENTEQ => Some((c, BinOp::RemAssign)),
159 SHREQ => Some((c, BinOp::ShrAssign)),
160 SHLEQ => Some((c, BinOp::ShlAssign)),
161 MINUSEQ => Some((c, BinOp::SubAssign)),
162 PIPEEQ => Some((c, BinOp::BitOrAssign)),
163 AMPEQ => Some((c, BinOp::BitAndAssign)),
164 CARETEQ => Some((c, BinOp::BitXorAssign)),
165 _ => None,
166 }
167 })
168 }
169
170 pub fn op_kind(&self) -> Option<BinOp> {
171 self.op_details().map(|t| t.1)
172 }
173
174 pub fn op_token(&self) -> Option<SyntaxToken> {
175 self.op_details().map(|t| t.0)
176 }
177
178 pub fn lhs(&self) -> Option<&ast::Expr> {
179 children(self).nth(0)
180 }
181
182 pub fn rhs(&self) -> Option<&ast::Expr> {
183 children(self).nth(1)
184 }
185
186 pub fn sub_exprs(&self) -> (Option<&ast::Expr>, Option<&ast::Expr>) {
187 let mut children = children(self);
188 let first = children.next();
189 let second = children.next();
190 (first, second)
191 }
192}
193
194#[derive(Clone, Debug, PartialEq, Eq, Hash)]
195pub enum LiteralFlavor {
196 String,
197 ByteString,
198 Char,
199 Byte,
200 IntNumber { suffix: Option<SmolStr> },
201 FloatNumber { suffix: Option<SmolStr> },
202 Bool,
203}
204
205impl ast::Literal {
206 pub fn token(&self) -> SyntaxToken {
207 match self.syntax().first_child_or_token().unwrap() {
208 SyntaxElement::Token(token) => token,
209 _ => unreachable!(),
210 }
211 }
212
213 pub fn flavor(&self) -> LiteralFlavor {
214 match self.token().kind() {
215 INT_NUMBER => {
216 let allowed_suffix_list = [
217 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32",
218 "u16", "u8",
219 ];
220 let text = self.token().text().to_string();
221 let suffix = allowed_suffix_list
222 .iter()
223 .find(|&s| text.ends_with(s))
224 .map(|&suf| SmolStr::new(suf));
225 LiteralFlavor::IntNumber { suffix }
226 }
227 FLOAT_NUMBER => {
228 let allowed_suffix_list = ["f64", "f32"];
229 let text = self.token().text().to_string();
230 let suffix = allowed_suffix_list
231 .iter()
232 .find(|&s| text.ends_with(s))
233 .map(|&suf| SmolStr::new(suf));
234 LiteralFlavor::FloatNumber { suffix: suffix }
235 }
236 STRING | RAW_STRING => LiteralFlavor::String,
237 TRUE_KW | FALSE_KW => LiteralFlavor::Bool,
238 BYTE_STRING | RAW_BYTE_STRING => LiteralFlavor::ByteString,
239 CHAR => LiteralFlavor::Char,
240 BYTE => LiteralFlavor::Byte,
241 _ => unreachable!(),
242 }
243 }
244}
245
246impl ast::NamedField {
247 pub fn parent_struct_lit(&self) -> &ast::StructLit {
248 self.syntax().ancestors().find_map(ast::StructLit::cast).unwrap()
249 }
250}