Parse and infer tuple indices
This commit is contained in:
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
@@ -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<SyntaxToken> {
|
||||
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<FieldKind> {
|
||||
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)
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<SyntaxError> {
|
||||
let _ = visitor_ctx(&mut errors)
|
||||
.visit::<ast::Literal, _>(validate_literal)
|
||||
.visit::<ast::Block, _>(block::validate_block_node)
|
||||
.visit::<ast::FieldExpr, _>(field_expr::validate_field_expr_node)
|
||||
.accept(node);
|
||||
}
|
||||
errors
|
||||
|
||||
12
crates/ra_syntax/src/validation/field_expr.rs
Normal file
12
crates/ra_syntax/src/validation/field_expr.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use crate::{ast::{self, FieldKind},
|
||||
SyntaxError,
|
||||
SyntaxErrorKind::*,
|
||||
};
|
||||
|
||||
pub(crate) fn validate_field_expr_node(node: &ast::FieldExpr, errors: &mut Vec<SyntaxError>) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user