aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs22
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs34
-rw-r--r--crates/ra_syntax/src/syntax_error.rs4
-rw-r--r--crates/ra_syntax/src/validation.rs2
-rw-r--r--crates/ra_syntax/src/validation/field_expr.rs12
6 files changed, 71 insertions, 7 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 9f5c41b0c..c2ab19d97 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -17,8 +17,8 @@ pub use self::{
17 generated::*, 17 generated::*,
18 traits::*, 18 traits::*,
19 tokens::*, 19 tokens::*,
20 extensions::{PathSegmentKind, StructKind, SelfParamKind}, 20 extensions::{PathSegmentKind, StructKind,FieldKind, SelfParamKind},
21 expr_extensions::{ElseBranch, PrefixOp, BinOp, LiteralKind}, 21 expr_extensions::{ElseBranch, PrefixOp, BinOp, LiteralKind,ArrayExprKind},
22}; 22};
23 23
24/// The main trait to go from untyped `SyntaxNode` to a typed ast. The 24/// The main trait to go from untyped `SyntaxNode` to a typed ast. The
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 1d8313810..9484c3b9b 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -193,6 +193,28 @@ impl ast::BinExpr {
193 } 193 }
194} 194}
195 195
196pub enum ArrayExprKind<'a> {
197 Repeat { initializer: Option<&'a ast::Expr>, repeat: Option<&'a ast::Expr> },
198 ElementList(AstChildren<'a, ast::Expr>),
199}
200
201impl ast::ArrayExpr {
202 pub fn kind(&self) -> ArrayExprKind {
203 if self.is_repeat() {
204 ArrayExprKind::Repeat {
205 initializer: children(self).nth(0),
206 repeat: children(self).nth(1),
207 }
208 } else {
209 ArrayExprKind::ElementList(children(self))
210 }
211 }
212
213 fn is_repeat(&self) -> bool {
214 self.syntax().children_with_tokens().any(|it| it.kind() == SEMI)
215 }
216}
217
196#[derive(Clone, Debug, PartialEq, Eq, Hash)] 218#[derive(Clone, Debug, PartialEq, Eq, Hash)]
197pub enum LiteralKind { 219pub enum LiteralKind {
198 String, 220 String,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index aec57c380..ca33b43e7 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -3,11 +3,8 @@
3 3
4use itertools::Itertools; 4use itertools::Itertools;
5 5
6use crate::{ 6use crate::{SmolStr, SyntaxToken, ast::{self, AstNode, children, child_opt}, SyntaxKind::*, SyntaxElement};
7 SmolStr, SyntaxToken, 7use ra_parser::SyntaxKind;
8 ast::{self, AstNode, children, child_opt},
9 SyntaxKind::*,
10};
11 8
12impl ast::Name { 9impl ast::Name {
13 pub fn text(&self) -> &SmolStr { 10 pub fn text(&self) -> &SmolStr {
@@ -217,6 +214,33 @@ impl ast::ExprStmt {
217 } 214 }
218} 215}
219 216
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub enum FieldKind<'a> {
219 Name(&'a ast::NameRef),
220 Index(SyntaxToken<'a>),
221}
222
223impl ast::FieldExpr {
224 pub fn index_token(&self) -> Option<SyntaxToken> {
225 self.syntax
226 .children_with_tokens()
227 // FIXME: Accepting floats here to reject them in validation later
228 .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
229 .as_ref()
230 .and_then(SyntaxElement::as_token)
231 }
232
233 pub fn field_access(&self) -> Option<FieldKind> {
234 if let Some(nr) = self.name_ref() {
235 Some(FieldKind::Name(nr))
236 } else if let Some(tok) = self.index_token() {
237 Some(FieldKind::Index(tok))
238 } else {
239 None
240 }
241 }
242}
243
220impl ast::RefPat { 244impl ast::RefPat {
221 pub fn is_mut(&self) -> bool { 245 pub fn is_mut(&self) -> bool {
222 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW) 246 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs
index 4b8c22a57..4198eefdb 100644
--- a/crates/ra_syntax/src/syntax_error.rs
+++ b/crates/ra_syntax/src/syntax_error.rs
@@ -95,6 +95,7 @@ pub enum SyntaxErrorKind {
95 InvalidSuffix, 95 InvalidSuffix,
96 InvalidBlockAttr, 96 InvalidBlockAttr,
97 InvalidMatchInnerAttr, 97 InvalidMatchInnerAttr,
98 InvalidTupleIndexFormat,
98} 99}
99 100
100impl fmt::Display for SyntaxErrorKind { 101impl fmt::Display for SyntaxErrorKind {
@@ -139,6 +140,9 @@ impl fmt::Display for SyntaxErrorKind {
139 InvalidMatchInnerAttr => { 140 InvalidMatchInnerAttr => {
140 write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression") 141 write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression")
141 } 142 }
143 InvalidTupleIndexFormat => {
144 write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix")
145 }
142 ParseError(msg) => write!(f, "{}", msg.0), 146 ParseError(msg) => write!(f, "{}", msg.0),
143 } 147 }
144 } 148 }
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index fc534df83..c2f545173 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -3,6 +3,7 @@ mod byte_string;
3mod char; 3mod char;
4mod string; 4mod string;
5mod block; 5mod block;
6mod field_expr;
6 7
7use crate::{ 8use crate::{
8 SourceFile, SyntaxError, AstNode, SyntaxNode, 9 SourceFile, SyntaxError, AstNode, SyntaxNode,
@@ -17,6 +18,7 @@ pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> {
17 let _ = visitor_ctx(&mut errors) 18 let _ = visitor_ctx(&mut errors)
18 .visit::<ast::Literal, _>(validate_literal) 19 .visit::<ast::Literal, _>(validate_literal)
19 .visit::<ast::Block, _>(block::validate_block_node) 20 .visit::<ast::Block, _>(block::validate_block_node)
21 .visit::<ast::FieldExpr, _>(field_expr::validate_field_expr_node)
20 .accept(node); 22 .accept(node);
21 } 23 }
22 errors 24 errors
diff --git a/crates/ra_syntax/src/validation/field_expr.rs b/crates/ra_syntax/src/validation/field_expr.rs
new file mode 100644
index 000000000..2b405062e
--- /dev/null
+++ b/crates/ra_syntax/src/validation/field_expr.rs
@@ -0,0 +1,12 @@
1use crate::{ast::{self, FieldKind},
2 SyntaxError,
3 SyntaxErrorKind::*,
4};
5
6pub(crate) fn validate_field_expr_node(node: &ast::FieldExpr, errors: &mut Vec<SyntaxError>) {
7 if let Some(FieldKind::Index(idx)) = node.field_access() {
8 if idx.text().chars().any(|c| c < '0' || c > '9') {
9 errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.range()));
10 }
11 }
12}