From ca40ca93a55ffa08d3e699fc877e7e189b526c66 Mon Sep 17 00:00:00 2001 From: robojumper Date: Fri, 5 Apr 2019 22:34:45 +0200 Subject: Parse and infer tuple indices --- crates/ra_syntax/src/ast.rs | 2 +- crates/ra_syntax/src/ast/extensions.rs | 34 +++++++++++++++++++++++---- crates/ra_syntax/src/syntax_error.rs | 4 ++++ crates/ra_syntax/src/validation.rs | 2 ++ crates/ra_syntax/src/validation/field_expr.rs | 12 ++++++++++ 5 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 crates/ra_syntax/src/validation/field_expr.rs (limited to 'crates/ra_syntax/src') diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index 9f5c41b0c..a06a6375d 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs @@ -17,7 +17,7 @@ pub use self::{ generated::*, traits::*, tokens::*, - extensions::{PathSegmentKind, StructKind, SelfParamKind}, + extensions::{PathSegmentKind, StructKind, FieldKind, SelfParamKind}, expr_extensions::{ElseBranch, PrefixOp, BinOp, LiteralKind}, }; 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 @@ use itertools::Itertools; -use crate::{ - SmolStr, SyntaxToken, - ast::{self, AstNode, children, child_opt}, - SyntaxKind::*, -}; +use crate::{SmolStr, SyntaxToken, ast::{self, AstNode, children, child_opt}, SyntaxKind::*, SyntaxElement}; +use ra_parser::SyntaxKind; impl ast::Name { pub fn text(&self) -> &SmolStr { @@ -217,6 +214,33 @@ impl ast::ExprStmt { } } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum FieldKind<'a> { + Name(&'a ast::NameRef), + Index(SyntaxToken<'a>), +} + +impl ast::FieldExpr { + pub fn index_token(&self) -> Option { + self.syntax + .children_with_tokens() + // FIXME: Accepting floats here to reject them in validation later + .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER) + .as_ref() + .and_then(SyntaxElement::as_token) + } + + pub fn field_access(&self) -> Option { + if let Some(nr) = self.name_ref() { + Some(FieldKind::Name(nr)) + } else if let Some(tok) = self.index_token() { + Some(FieldKind::Index(tok)) + } else { + None + } + } +} + impl ast::RefPat { pub fn is_mut(&self) -> bool { 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 { InvalidSuffix, InvalidBlockAttr, InvalidMatchInnerAttr, + InvalidTupleIndexFormat, } impl fmt::Display for SyntaxErrorKind { @@ -139,6 +140,9 @@ impl fmt::Display for SyntaxErrorKind { InvalidMatchInnerAttr => { write!(f, "Inner attributes are only allowed directly after the opening brace of the match expression") } + InvalidTupleIndexFormat => { + write!(f, "Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix") + } ParseError(msg) => write!(f, "{}", msg.0), } } 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; mod char; mod string; mod block; +mod field_expr; use crate::{ SourceFile, SyntaxError, AstNode, SyntaxNode, @@ -17,6 +18,7 @@ pub(crate) fn validate(file: &SourceFile) -> Vec { let _ = visitor_ctx(&mut errors) .visit::(validate_literal) .visit::(block::validate_block_node) + .visit::(field_expr::validate_field_expr_node) .accept(node); } 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 @@ +use crate::{ast::{self, FieldKind}, + SyntaxError, + SyntaxErrorKind::*, +}; + +pub(crate) fn validate_field_expr_node(node: &ast::FieldExpr, errors: &mut Vec) { + if let Some(FieldKind::Index(idx)) = node.field_access() { + if idx.text().chars().any(|c| c < '0' || c > '9') { + errors.push(SyntaxError::new(InvalidTupleIndexFormat, idx.range())); + } + } +} -- cgit v1.2.3