From a68aefdc463af054e7e98293c06b751c135911d5 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Fri, 15 Nov 2019 01:04:37 -0800 Subject: Move inclusive range check to validation --- crates/ra_syntax/src/syntax_error.rs | 4 ++++ crates/ra_syntax/src/validation.rs | 14 ++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'crates/ra_syntax/src') 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 { InvalidMatchInnerAttr, InvalidTupleIndexFormat, VisibilityNotAllowed, + InclusiveRangeMissingEnd, } impl fmt::Display for SyntaxErrorKind { @@ -103,6 +104,9 @@ impl fmt::Display for SyntaxErrorKind { VisibilityNotAllowed => { write!(f, "unnecessary visibility qualifier") } + InclusiveRangeMissingEnd => { + write!(f, "An inclusive range must have an end expression") + } } } } diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 2d596763e..e01333e23 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 { ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, ast::Visibility(it) => { validate_visibility(it, &mut errors) }, + ast::RangeExpr(it) => { validate_range_expr(it, &mut errors) }, _ => (), } } @@ -227,3 +228,16 @@ fn validate_visibility(vis: ast::Visibility, errors: &mut Vec) { .push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range())) } } + +fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec) { + let last_child = match expr.syntax().last_child_or_token() { + Some(it) => it, + None => return, + }; + if last_child.kind() == T![..=] { + errors.push(SyntaxError::new( + SyntaxErrorKind::InclusiveRangeMissingEnd, + last_child.text_range(), + )); + } +} -- cgit v1.2.3 From 5645c153e0379874d1f44ab149c3ec9257812692 Mon Sep 17 00:00:00 2001 From: Geoffry Song Date: Fri, 15 Nov 2019 12:05:29 -0800 Subject: Attempt to implement typed accessors --- crates/ra_syntax/src/ast.rs | 2 +- crates/ra_syntax/src/ast/expr_extensions.rs | 46 +++++++++++++++++++++++++++++ crates/ra_syntax/src/validation.rs | 8 ++--- 3 files changed, 49 insertions(+), 7 deletions(-) (limited to 'crates/ra_syntax/src') 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::{ }; pub use self::{ - expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp}, + expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp}, extensions::{FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind}, generated::*, 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 { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum RangeOp { + /// `..` + Exclusive, + /// `..=` + Inclusive, +} + +impl ast::RangeExpr { + fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> { + self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| { + let token = child.into_token()?; + let bin_op = match token.kind() { + T![..] => RangeOp::Exclusive, + T![..=] => RangeOp::Inclusive, + _ => return None, + }; + Some((ix, token, bin_op)) + }) + } + + pub fn op_kind(&self) -> Option { + self.op_details().map(|t| t.2) + } + + pub fn op_token(&self) -> Option { + self.op_details().map(|t| t.1) + } + + pub fn start(&self) -> Option { + let op_ix = self.op_details()?.0; + self.syntax() + .children_with_tokens() + .take(op_ix) + .find_map(|it| ast::Expr::cast(it.into_node()?)) + } + + pub fn end(&self) -> Option { + let op_ix = self.op_details()?.0; + self.syntax() + .children_with_tokens() + .skip(op_ix + 1) + .find_map(|it| ast::Expr::cast(it.into_node()?)) + } +} + impl ast::IndexExpr { pub fn base(&self) -> Option { children(self).nth(0) diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index e01333e23..222ac15f8 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -230,14 +230,10 @@ fn validate_visibility(vis: ast::Visibility, errors: &mut Vec) { } fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec) { - let last_child = match expr.syntax().last_child_or_token() { - Some(it) => it, - None => return, - }; - if last_child.kind() == T![..=] { + if expr.op_kind() == Some(ast::RangeOp::Inclusive) && expr.end().is_none() { errors.push(SyntaxError::new( SyntaxErrorKind::InclusiveRangeMissingEnd, - last_child.text_range(), + expr.syntax().text_range(), )); } } -- cgit v1.2.3