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.rs2
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs46
-rw-r--r--crates/ra_syntax/src/syntax_error.rs4
-rw-r--r--crates/ra_syntax/src/validation.rs10
4 files changed, 61 insertions, 1 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 1ec9881b9..277532a8c 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -16,7 +16,7 @@ use crate::{
16}; 16};
17 17
18pub use self::{ 18pub use self::{
19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp}, 19 expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
20 extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind}, 20 extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind},
21 generated::*, 21 generated::*,
22 tokens::*, 22 tokens::*,
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 25dbd0bed..7c53aa934 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -189,6 +189,52 @@ impl ast::BinExpr {
189 } 189 }
190} 190}
191 191
192#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
193pub enum RangeOp {
194 /// `..`
195 Exclusive,
196 /// `..=`
197 Inclusive,
198}
199
200impl ast::RangeExpr {
201 fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
202 self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {
203 let token = child.into_token()?;
204 let bin_op = match token.kind() {
205 T![..] => RangeOp::Exclusive,
206 T![..=] => RangeOp::Inclusive,
207 _ => return None,
208 };
209 Some((ix, token, bin_op))
210 })
211 }
212
213 pub fn op_kind(&self) -> Option<RangeOp> {
214 self.op_details().map(|t| t.2)
215 }
216
217 pub fn op_token(&self) -> Option<SyntaxToken> {
218 self.op_details().map(|t| t.1)
219 }
220
221 pub fn start(&self) -> Option<ast::Expr> {
222 let op_ix = self.op_details()?.0;
223 self.syntax()
224 .children_with_tokens()
225 .take(op_ix)
226 .find_map(|it| ast::Expr::cast(it.into_node()?))
227 }
228
229 pub fn end(&self) -> Option<ast::Expr> {
230 let op_ix = self.op_details()?.0;
231 self.syntax()
232 .children_with_tokens()
233 .skip(op_ix + 1)
234 .find_map(|it| ast::Expr::cast(it.into_node()?))
235 }
236}
237
192impl ast::IndexExpr { 238impl ast::IndexExpr {
193 pub fn base(&self) -> Option<ast::Expr> { 239 pub fn base(&self) -> Option<ast::Expr> {
194 children(self).nth(0) 240 children(self).nth(0)
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs
index 1f60a7aab..6c171df8d 100644
--- a/crates/ra_syntax/src/syntax_error.rs
+++ b/crates/ra_syntax/src/syntax_error.rs
@@ -83,6 +83,7 @@ pub enum SyntaxErrorKind {
83 InvalidMatchInnerAttr, 83 InvalidMatchInnerAttr,
84 InvalidTupleIndexFormat, 84 InvalidTupleIndexFormat,
85 VisibilityNotAllowed, 85 VisibilityNotAllowed,
86 InclusiveRangeMissingEnd,
86} 87}
87 88
88impl fmt::Display for SyntaxErrorKind { 89impl fmt::Display for SyntaxErrorKind {
@@ -103,6 +104,9 @@ impl fmt::Display for SyntaxErrorKind {
103 VisibilityNotAllowed => { 104 VisibilityNotAllowed => {
104 write!(f, "unnecessary visibility qualifier") 105 write!(f, "unnecessary visibility qualifier")
105 } 106 }
107 InclusiveRangeMissingEnd => {
108 write!(f, "An inclusive range must have an end expression")
109 }
106 } 110 }
107 } 111 }
108} 112}
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 2d596763e..222ac15f8 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -103,6 +103,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
103 ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, 103 ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) },
104 ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, 104 ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) },
105 ast::Visibility(it) => { validate_visibility(it, &mut errors) }, 105 ast::Visibility(it) => { validate_visibility(it, &mut errors) },
106 ast::RangeExpr(it) => { validate_range_expr(it, &mut errors) },
106 _ => (), 107 _ => (),
107 } 108 }
108 } 109 }
@@ -227,3 +228,12 @@ fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
227 .push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range())) 228 .push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range()))
228 } 229 }
229} 230}
231
232fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
233 if expr.op_kind() == Some(ast::RangeOp::Inclusive) && expr.end().is_none() {
234 errors.push(SyntaxError::new(
235 SyntaxErrorKind::InclusiveRangeMissingEnd,
236 expr.syntax().text_range(),
237 ));
238 }
239}