diff --git a/crates/hir/src/lower/parse.rs b/crates/hir/src/lower/parse.rs index 81deadeb6..d2c8ff7b7 100644 --- a/crates/hir/src/lower/parse.rs +++ b/crates/hir/src/lower/parse.rs @@ -47,7 +47,7 @@ impl DiagnosticVoucher for ParserError { self.error.msg(), vec![SubDiagnostic::new( LabelStyle::Primary, - self.error.msg(), + self.error.label(), Some(span), )], vec![], diff --git a/crates/hir/src/visitor.rs b/crates/hir/src/visitor.rs index 158b0c6d8..60a32d887 100644 --- a/crates/hir/src/visitor.rs +++ b/crates/hir/src/visitor.rs @@ -2171,8 +2171,8 @@ mod tests { fn visitor() { let mut db = TestDb::default(); let text = r#" - #[attr1] - #[attr2] + #attr1 + #attr2 fn foo() { 1 "foo" @@ -2197,8 +2197,8 @@ mod tests { ); assert_eq!(visitor.attributes.len(), 2); - assert_eq!("#[attr1]", db.text_at(top_mod, &visitor.attributes[0])); - assert_eq!("#[attr2]", db.text_at(top_mod, &visitor.attributes[1])); + assert_eq!("#attr1", db.text_at(top_mod, &visitor.attributes[0])); + assert_eq!("#attr2", db.text_at(top_mod, &visitor.attributes[1])); assert_eq!(visitor.lit_ints.len(), 2); assert_eq!("1", db.text_at(top_mod, &visitor.lit_ints[0])); diff --git a/crates/parser2/src/ast/expr.rs b/crates/parser2/src/ast/expr.rs index b3f6dd1df..e3a1a8dde 100644 --- a/crates/parser2/src/ast/expr.rs +++ b/crates/parser2/src/ast/expr.rs @@ -913,7 +913,6 @@ mod tests { let if_expr: IfExpr = parse_expr("if { true } { return } else { continue }"); if let ExprKind::Block(stmts) = if_expr.cond().unwrap().kind() { - dbg!(&stmts); assert!(matches!( stmts.into_iter().next().unwrap().kind(), crate::ast::StmtKind::Expr(_) diff --git a/crates/parser2/src/ast/item.rs b/crates/parser2/src/ast/item.rs index a97315bbc..15e15dbad 100644 --- a/crates/parser2/src/ast/item.rs +++ b/crates/parser2/src/ast/item.rs @@ -549,7 +549,6 @@ mod tests { } "#; let s: Struct = parse_item(source); - dbg!(&s); assert_eq!(s.name().unwrap().text(), "Foo"); let mut count = 0; for field in s.fields().unwrap() { diff --git a/crates/parser2/src/lib.rs b/crates/parser2/src/lib.rs index 3176dfee0..1c0905578 100644 --- a/crates/parser2/src/lib.rs +++ b/crates/parser2/src/lib.rs @@ -26,25 +26,51 @@ pub fn parse_source_file(text: &str) -> (GreenNode, Vec) { /// An parse error which is accumulated in the [`parser::Parser`] while parsing. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ParseError { - Expected(SmallVec<[SyntaxKind; 2]>, Option, TextSize), - Unexpected(TextRange), - + Expected(SmallVec<[SyntaxKind; 2]>, ExpectedKind, TextSize), + Unexpected(String, TextRange), Msg(String, TextRange), } impl ParseError { - pub fn expected(tokens: &[SyntaxKind], msg: Option<&str>, pos: TextSize) -> Self { + pub fn expected(tokens: &[SyntaxKind], kind: Option, pos: TextSize) -> Self { ParseError::Expected( SmallVec::from_slice(tokens), - msg.map(|s| s.to_string()), + kind.unwrap_or(ExpectedKind::Unspecified), pos, ) } pub fn msg(&self) -> String { match self { - ParseError::Expected(_, Some(msg), _) => msg.clone(), - ParseError::Expected(tokens, None, _) => { + ParseError::Expected(_, exp, _) => match exp { + ExpectedKind::Body(kind) => format!("{} requires a body", kind.describe()), + ExpectedKind::Name(kind) => format!("expected name for {}", kind.describe()), + ExpectedKind::ClosingBracket { bracket, parent } => format!( + "missing closing {} for {}", + bracket.describe(), + parent.describe() + ), + ExpectedKind::Separator { separator, element } => { + format!( + "expected {} separator after {}", + separator.describe(), + element.describe() + ) + } + ExpectedKind::TypeSpecifier(kind) => { + format!("missing type bound for {}", kind.describe()) + } + ExpectedKind::Syntax(kind) => format!("expected {}", kind.describe()), + ExpectedKind::Unspecified => self.label(), + }, + ParseError::Unexpected(m, _) => m.clone(), + ParseError::Msg(m, _) => m.clone(), + } + } + + pub fn label(&self) -> String { + match self { + ParseError::Expected(tokens, _, _) => { if tokens.len() == 1 { return format!("expected {}", tokens[0].describe()); } @@ -59,15 +85,35 @@ impl ParseError { } s } - ParseError::Unexpected(_) => "unexpected syntax".into(), - ParseError::Msg(m, _) => m.clone(), + ParseError::Unexpected(_, _) => "unexpected".into(), + ParseError::Msg(msg, _) => msg.clone(), } } pub fn range(&self) -> TextRange { match self { ParseError::Expected(_, _, pos) => TextRange::empty(*pos), - ParseError::Unexpected(r) | ParseError::Msg(_, r) => *r, + ParseError::Unexpected(_, r) | ParseError::Msg(_, r) => *r, } } } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ExpectedKind { + Body(SyntaxKind), + Name(SyntaxKind), + ClosingBracket { + bracket: SyntaxKind, + parent: SyntaxKind, + }, + TypeSpecifier(SyntaxKind), + Separator { + separator: SyntaxKind, + element: SyntaxKind, + }, + Syntax(SyntaxKind), + Unspecified, + // TODO: + // - newline after attribute in attrlistscope + // +} diff --git a/crates/parser2/src/parser/attr.rs b/crates/parser2/src/parser/attr.rs index 19286d582..e767976cf 100644 --- a/crates/parser2/src/parser/attr.rs +++ b/crates/parser2/src/parser/attr.rs @@ -5,7 +5,7 @@ use super::{ define_scope, parse_list, token_stream::TokenStream, Checkpoint, ErrProof, Parser, Recovery, }; -use crate::SyntaxKind; +use crate::{ExpectedKind, SyntaxKind}; pub(super) fn parse_attr_list( parser: &mut Parser, @@ -40,7 +40,13 @@ impl super::Parse for AttrListScope { _ => break, }; parser.set_newline_as_trivia(false); - if parser.find(SyntaxKind::Newline, None)? { + if parser.find( + SyntaxKind::Newline, + ExpectedKind::Separator { + separator: SyntaxKind::Newline, + element: SyntaxKind::Attr, + }, + )? { parser.bump(); } } @@ -61,10 +67,7 @@ impl super::Parse for AttrScope { parser.bump_expected(SyntaxKind::Pound); parser.set_scope_recovery_stack(&[SyntaxKind::LParen]); - if parser.find( - SyntaxKind::Ident, - Some("expected an attribute name after `#`"), - )? { + if parser.find(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Attr))? { parser.bump() } @@ -89,6 +92,7 @@ impl super::Parse for AttrArgListScope { parse_list( parser, false, + SyntaxKind::AttrArgList, (SyntaxKind::LParen, SyntaxKind::RParen), |parser| parser.parse(AttrArgScope::default()), ) @@ -104,16 +108,16 @@ impl super::Parse for AttrArgScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - let msg = Some("expected attribute argument in the form `key: value`"); + let expected_err = ExpectedKind::Syntax(SyntaxKind::AttrArg); parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::Colon]); - if parser.find_and_pop(SyntaxKind::Ident, msg)? { + if parser.find_and_pop(SyntaxKind::Ident, expected_err)? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::Colon, msg)? { + if parser.find_and_pop(SyntaxKind::Colon, expected_err)? { parser.bump(); } - if parser.find(SyntaxKind::Ident, msg)? { + if parser.find(SyntaxKind::Ident, expected_err)? { parser.bump(); } Ok(()) diff --git a/crates/parser2/src/parser/expr.rs b/crates/parser2/src/parser/expr.rs index 53862fe2e..e44088834 100644 --- a/crates/parser2/src/parser/expr.rs +++ b/crates/parser2/src/parser/expr.rs @@ -1,13 +1,14 @@ -use std::convert::Infallible; +use std::convert::{identity, Infallible}; use unwrap_infallible::UnwrapInfallible; use super::{ - define_scope, expr_atom, + define_scope, + expr_atom::{self, is_expr_atom_head}, param::{CallArgListScope, GenericArgListScope}, token_stream::TokenStream, Checkpoint, ErrProof, Parser, Recovery, }; -use crate::SyntaxKind; +use crate::{ExpectedKind, SyntaxKind}; /// Parses expression. pub fn parse_expr(parser: &mut Parser) -> Result<(), Recovery> { @@ -112,8 +113,10 @@ fn parse_expr_atom( Some(kind) if prefix_binding_power(kind).is_some() => { parser.parse_cp(UnExprScope::default(), None) } - Some(_) => expr_atom::parse_expr_atom(parser, allow_struct_init), - None => parser + Some(kind) if is_expr_atom_head(kind) => { + expr_atom::parse_expr_atom(parser, allow_struct_init) + } + _ => parser .error_and_recover("expected expression") .map(|_| parser.checkpoint()), } @@ -273,7 +276,10 @@ impl super::Parse for IndexExprScope { if parser.find( SyntaxKind::RBracket, - Some("missing closing `]` in index expression"), + ExpectedKind::ClosingBracket { + bracket: SyntaxKind::RBracket, + parent: SyntaxKind::IndexExpr, + }, )? { parser.bump(); } @@ -293,7 +299,10 @@ impl super::Parse for CallExprScope { parser.parse(GenericArgListScope::default())?; } - if parser.find_and_pop(SyntaxKind::LParen, None)? { + if parser.find_and_pop( + SyntaxKind::LParen, + ExpectedKind::Syntax(SyntaxKind::CallArgList), + )? { parser.parse(CallArgListScope::default())?; } Ok(()) @@ -309,7 +318,10 @@ impl super::Parse for MethodExprScope { parser.set_newline_as_trivia(false); parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::Lt, SyntaxKind::LParen]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop( + SyntaxKind::Ident, + ExpectedKind::Name(SyntaxKind::MethodCallExpr), + )? { parser.bump(); } @@ -318,7 +330,10 @@ impl super::Parse for MethodExprScope { parser.parse(GenericArgListScope::default())?; } - if parser.find_and_pop(SyntaxKind::LParen, None)? { + if parser.find_and_pop( + SyntaxKind::LParen, + ExpectedKind::Syntax(SyntaxKind::CallArgList), + )? { parser.parse(CallArgListScope::default())?; } Ok(()) @@ -472,14 +487,18 @@ fn is_call_expr(parser: &mut Parser) -> bool { let mut is_call = true; if parser.current_kind() == Some(SyntaxKind::Lt) { - // xxx `call` error recovery test: "without error" should only apply to base scope - is_call &= parser.parses_without_error(GenericArgListScope::default()) + is_call &= parser + .parse_ok(GenericArgListScope::default()) + .is_ok_and(identity) } if parser.current_kind() != Some(SyntaxKind::LParen) { false } else { - is_call && parser.parses_without_error(CallArgListScope::default()) + is_call + && parser + .parse_ok(CallArgListScope::default()) + .is_ok_and(identity) } }) } @@ -496,7 +515,9 @@ fn is_method_call(parser: &mut Parser) -> bool { } if parser.current_kind() == Some(SyntaxKind::Lt) - && !parser.parses_without_error(GenericArgListScope::default()) + && !parser + .parse_ok(GenericArgListScope::default()) + .is_ok_and(identity) { return false; } @@ -505,7 +526,9 @@ fn is_method_call(parser: &mut Parser) -> bool { false } else { parser.set_newline_as_trivia(is_trivia); - parser.parses_without_error(CallArgListScope::default()) + parser + .parse_ok(CallArgListScope::default()) + .is_ok_and(identity) } }); parser.set_newline_as_trivia(is_trivia); diff --git a/crates/parser2/src/parser/expr_atom.rs b/crates/parser2/src/parser/expr_atom.rs index 586f1934a..e966e44ec 100644 --- a/crates/parser2/src/parser/expr_atom.rs +++ b/crates/parser2/src/parser/expr_atom.rs @@ -4,7 +4,7 @@ use rowan::Checkpoint; use crate::{ parser::{lit, path}, - SyntaxKind, + ExpectedKind, SyntaxKind, TextRange, }; use super::{ @@ -17,6 +17,18 @@ use super::{ ErrProof, Parser, Recovery, }; +// Must be kept in sync with `parse_expr_atom` +pub(super) fn is_expr_atom_head(kind: SyntaxKind) -> bool { + use SyntaxKind::*; + match kind { + IfKw | MatchKw | LBrace | LParen | LBracket => true, + kind if lit::is_lit(kind) => true, + kind if path::is_path_segment(kind) => true, + _ => false, + } +} + +/// Panics if `!is_expr_atom_head(parser.current_kind())` pub(super) fn parse_expr_atom( parser: &mut Parser, allow_record_init: bool, @@ -34,9 +46,7 @@ pub(super) fn parse_expr_atom( Some(kind) if path::is_path_segment(kind) => { parser.parse_cp(PathExprScope::new(allow_record_init), None) } - _ => parser - .error_and_recover("expected expression") // xxx - .map(|()| parser.checkpoint()), + _ => unreachable!(), } } @@ -83,7 +93,13 @@ impl super::Parse for BlockExprScope { parser.bump_if(SyntaxKind::Newline); } - if parser.find(SyntaxKind::RBrace, Some("missing closing `}` for block"))? { + if parser.find( + SyntaxKind::RBrace, + crate::ExpectedKind::ClosingBracket { + bracket: SyntaxKind::RBrace, + parent: SyntaxKind::BlockExpr, + }, + )? { parser.bump(); } Ok(()) @@ -100,7 +116,7 @@ impl super::Parse for IfExprScope { parser.set_scope_recovery_stack(&[SyntaxKind::LBrace, SyntaxKind::ElseKw]); parse_expr_no_struct(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, Some("missing `if` body"))? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::IfExpr))? { parser.parse(BlockExprScope::default())?; } @@ -122,8 +138,10 @@ impl super::Parse for MatchExprScope { parser.bump_expected(SyntaxKind::MatchKw); parse_expr_no_struct(parser)?; - if parser.find(SyntaxKind::LBrace, None)? { - dbg!(parser.current_kind()); + if parser.find( + SyntaxKind::LBrace, + ExpectedKind::Body(SyntaxKind::MatchExpr), + )? { parser.parse(MatchArmListScope::default())?; } Ok(()) @@ -166,7 +184,7 @@ impl super::Parse for MatchArmScope { parser.set_scope_recovery_stack(&[SyntaxKind::FatArrow]); parse_pat(parser)?; - if parser.find_and_pop(SyntaxKind::FatArrow, None)? { + if parser.find_and_pop(SyntaxKind::FatArrow, ExpectedKind::Unspecified)? { parser.bump(); } parse_expr(parser) @@ -188,8 +206,14 @@ impl super::Parse for PathExprScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - // xxx "expected an expression"? - parser.or_recover(|p| p.parse(path::PathScope::default()))?; + parser.or_recover(|p| { + p.parse(path::PathScope::default()).map_err(|_| { + crate::ParseError::Msg( + "expected an expression".into(), + TextRange::empty(p.end_of_prev_token), + ) + }) + })?; if parser.current_kind() == Some(SyntaxKind::LBrace) && self.allow_record_init { self.set_kind(SyntaxKind::RecordInitExpr); @@ -207,6 +231,7 @@ impl super::Parse for RecordFieldListScope { parse_list( parser, true, + SyntaxKind::RecordFieldList, (SyntaxKind::LBrace, SyntaxKind::RBrace), |parser| parser.parse(RecordFieldScope::default()), ) @@ -299,7 +324,10 @@ impl super::Parse for ArrayScope { if parser.find( SyntaxKind::RBracket, - Some("missing closing `]` in array definition"), + ExpectedKind::ClosingBracket { + bracket: SyntaxKind::RBracket, + parent: SyntaxKind::ArrayExpr, + }, )? { parser.bump(); } diff --git a/crates/parser2/src/parser/func.rs b/crates/parser2/src/parser/func.rs index 6af9f122d..e12872d33 100644 --- a/crates/parser2/src/parser/func.rs +++ b/crates/parser2/src/parser/func.rs @@ -1,4 +1,4 @@ -use crate::SyntaxKind; +use crate::{ExpectedKind, SyntaxKind}; use super::{ define_scope, @@ -49,8 +49,6 @@ fn parse_normal_fn_def_impl( parser: &mut Parser, allow_self: bool, ) -> Result<(), Recovery> { - // xxx check where newlines are allowed - parser.set_scope_recovery_stack(&[ SyntaxKind::Ident, SyntaxKind::Lt, @@ -60,14 +58,17 @@ fn parse_normal_fn_def_impl( SyntaxKind::LBrace, ]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Func))? { parser.bump(); } parser.expect_and_pop_recovery_stack()?; parse_generic_params_opt(parser, false)?; - if parser.find_and_pop(SyntaxKind::LParen, None)? { + if parser.find_and_pop( + SyntaxKind::LParen, + ExpectedKind::Syntax(SyntaxKind::FuncParamList), + )? { parser.parse(FuncParamListScope::new(allow_self))?; } @@ -79,7 +80,7 @@ fn parse_normal_fn_def_impl( parser.expect_and_pop_recovery_stack()?; parse_where_clause_opt(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, None)? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Func))? { parser.parse(BlockExprScope::default())?; } Ok(()) @@ -97,14 +98,17 @@ fn parse_trait_fn_def_impl( SyntaxKind::LBrace, ]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Func))? { parser.bump(); } parser.expect_and_pop_recovery_stack()?; parse_generic_params_opt(parser, false)?; - if parser.find_and_pop(SyntaxKind::LParen, None)? { + if parser.find_and_pop( + SyntaxKind::LParen, + ExpectedKind::Syntax(SyntaxKind::FuncParamList), + )? { parser.parse(FuncParamListScope::new(true))?; } @@ -127,11 +131,14 @@ fn parse_extern_fn_def_impl( ) -> Result<(), Recovery> { parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::LParen, SyntaxKind::Arrow]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Func))? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::LParen, None)? { + if parser.find_and_pop( + SyntaxKind::LParen, + ExpectedKind::Syntax(SyntaxKind::FuncParamList), + )? { parser.parse(FuncParamListScope::new(true))?; } diff --git a/crates/parser2/src/parser/item.rs b/crates/parser2/src/parser/item.rs index d0c9a415b..851775109 100644 --- a/crates/parser2/src/parser/item.rs +++ b/crates/parser2/src/parser/item.rs @@ -2,7 +2,7 @@ use std::{cell::Cell, convert::Infallible, rc::Rc}; use unwrap_infallible::UnwrapInfallible; -use crate::{parser::func::FuncScope, SyntaxKind}; +use crate::{parser::func::FuncScope, ExpectedKind, SyntaxKind}; use super::{ attr, define_scope, @@ -47,6 +47,7 @@ impl super::Parse for ItemListScope { if self.inside_mod { parser.bump_expected(LBrace); + parser.set_scope_recovery_stack(&[RBrace]); } loop { @@ -56,12 +57,34 @@ impl super::Parse for ItemListScope { } if parser.current_kind().is_none() { if self.inside_mod { - parser.error("`}` to close the module"); + parser.add_error(crate::ParseError::expected( + &[RBrace], + Some(ExpectedKind::ClosingBracket { + bracket: RBrace, + parent: Mod, + }), + parser.current_pos, + )); } break; } - parser.parse(ItemScope::default())?; + let ok = parser.parse_ok(ItemScope::default())?; + if parser.current_kind().is_none() || (self.inside_mod && parser.bump_if(RBrace)) { + break; + } + if ok { + parser.set_newline_as_trivia(false); + if parser.find( + Newline, + ExpectedKind::Separator { + separator: Newline, + element: Item, + }, + )? { + parser.bump(); + } + } } Ok(()) } @@ -91,7 +114,7 @@ impl super::Parse for ItemScope { }; if modifier.is_unsafe() && parser.current_kind() != Some(FnKw) { - parser.error("expected `fn` after `unsafe` keyword"); // xxx + parser.error("expected `fn` after `unsafe` keyword"); } else if modifier.is_pub() && matches!(parser.current_kind(), Some(ImplKw | ExternKw)) { let error_msg = format!( "`pub` can't be used for `{}`", @@ -100,6 +123,14 @@ impl super::Parse for ItemScope { parser.error(&error_msg); } + parser.expect( + &[ + ModKw, FnKw, StructKw, ContractKw, EnumKw, TraitKw, ImplKw, UseKw, ConstKw, + ExternKw, TypeKw, + ], + Some(ExpectedKind::Syntax(SyntaxKind::Item)), + )?; + match parser.current_kind() { Some(ModKw) => parser.parse_cp(ModScope::default(), checkpoint), Some(FnKw) => parser.parse_cp(FuncScope::default(), checkpoint), @@ -112,21 +143,10 @@ impl super::Parse for ItemScope { Some(ConstKw) => parser.parse_cp(ConstScope::default(), checkpoint), Some(ExternKw) => parser.parse_cp(ExternScope::default(), checkpoint), Some(TypeKw) => parser.parse_cp(TypeAliasScope::default(), checkpoint), - tok => parser - .error_and_recover(&format! {"expected item: but got {tok:?}"}) - .map(|_| checkpoint.unwrap_or_else(|| parser.checkpoint())), + _ => unreachable!(), }?; - parser.set_newline_as_trivia(false); - if parser.current_kind().is_some() && !parser.bump_if(SyntaxKind::Newline) { - // xxx - parser.bump_or_recover( - SyntaxKind::Newline, - "expected newline after item definition", - ) - } else { - Ok(()) - } + Ok(()) } } @@ -146,11 +166,13 @@ impl super::Parse for ItemModifierScope { Some(kind) if kind.is_modifier_head() => { let new_kind = modifier_kind.union(kind); if new_kind == modifier_kind { - parser.unexpected_token_error("duplicate modifier", None); + parser.unexpected_token_error(format!( + "duplicate {} modifier", + kind.describe(), + )); } else if kind == SyntaxKind::PubKw && modifier_kind.is_unsafe() { parser.unexpected_token_error( - "`pub` modifier must come before `unsafe`", - None, + "`pub` modifier must come before `unsafe`".into(), ); } else { parser.bump(); @@ -213,12 +235,16 @@ impl super::Parse for ModScope { fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { parser.bump_expected(SyntaxKind::ModKw); - parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::LBrace]); + parser.set_scope_recovery_stack(&[ + SyntaxKind::Ident, + SyntaxKind::LBrace, + SyntaxKind::RBrace, + ]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Mod))? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::LBrace, Some("`mod` body"))? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Mod))? { parser.parse(ItemListScope::new(true))?; } Ok(()) @@ -234,10 +260,10 @@ impl super::Parse for ContractScope { parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::LBrace]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Contract))? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::LBrace, Some("contract field definition"))? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Contract))? { parser.parse(RecordFieldDefListScope::default())?; } Ok(()) @@ -258,7 +284,7 @@ impl super::Parse for EnumScope { SyntaxKind::LBrace, ]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Enum))? { parser.bump(); } @@ -268,7 +294,7 @@ impl super::Parse for EnumScope { parser.pop_recovery_stack(); parse_where_clause_opt(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, Some("enum body definition"))? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Enum))? { parser.parse(VariantDefListScope::default())?; } Ok(()) @@ -283,6 +309,7 @@ impl super::Parse for VariantDefListScope { parse_list( parser, true, + SyntaxKind::VariantDefList, (SyntaxKind::LBrace, SyntaxKind::RBrace), |parser| parser.parse(VariantDefScope::default()), ) @@ -293,7 +320,6 @@ define_scope! { VariantDefScope, VariantDef, Inheritance } impl super::Parse for VariantDefScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - // xxx check for keywords when bumping ident parser.bump_or_recover(SyntaxKind::Ident, "expected ident for the variant name")?; if parser.current_kind() == Some(SyntaxKind::LParen) { @@ -309,8 +335,6 @@ define_scope! { TraitScope, Trait, Inheritance } impl super::Parse for TraitScope { type Error = Recovery; - // xxx add TraitSignature syntax kind - fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { parser.bump_expected(SyntaxKind::TraitKw); parser.set_scope_recovery_stack(&[ @@ -320,10 +344,7 @@ impl super::Parse for TraitScope { SyntaxKind::WhereKw, SyntaxKind::LBrace, ]); - if parser.find_and_pop( - SyntaxKind::Ident, - Some("expected identifier for the trait name"), - )? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Trait))? { parser.bump(); } @@ -338,14 +359,14 @@ impl super::Parse for TraitScope { parser.expect_and_pop_recovery_stack()?; parse_where_clause_opt(parser)?; - if parser.find(SyntaxKind::LBrace, Some("missing trait body"))? { + if parser.find(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Trait))? { parser.parse(TraitItemListScope::default())?; } Ok(()) } } -define_scope! {SuperTraitListScope, SuperTraitList, Inheritance(Plus)} // xxx remove Plus? +define_scope! {SuperTraitListScope, SuperTraitList, Inheritance(Plus)} impl super::Parse for SuperTraitListScope { type Error = Recovery; @@ -378,11 +399,10 @@ impl super::Parse for ImplScope { parse_generic_params_opt(parser, false)?; let is_impl_trait = parser.dry_run(|parser| { - // xxx reconsider, with new changes to parses_without_error - // We don't use `parses_without_error` here, because it's too strict; - // we only care whether the token after the trait/type is `for`. - let _ = parse_type(parser, None); - parser.bump_if(SyntaxKind::ForKw) + parser.parse(TraitRefScope::default()).is_ok() + && parser + .find(SyntaxKind::ForKw, ExpectedKind::Unspecified) + .is_ok_and(|x| x) }); if is_impl_trait { @@ -394,8 +414,9 @@ impl super::Parse for ImplScope { ]); parser.parse(TraitRefScope::default())?; - parser.pop_recovery_stack(); - parser.bump_expected(SyntaxKind::ForKw); + if parser.find_and_pop(SyntaxKind::ForKw, ExpectedKind::Unspecified)? { + parser.bump(); + } } else { parser.set_scope_recovery_stack(&[SyntaxKind::WhereKw, SyntaxKind::LBrace]); } @@ -405,7 +426,10 @@ impl super::Parse for ImplScope { parser.expect_and_pop_recovery_stack()?; parse_where_clause_opt(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, Some("impl body"))? { + if parser.find_and_pop( + SyntaxKind::LBrace, + ExpectedKind::Body(SyntaxKind::ImplTrait), + )? { if is_impl_trait { parser.parse(ImplTraitItemListScope::default())?; } else { @@ -454,17 +478,19 @@ impl super::Parse for ConstScope { parser.set_newline_as_trivia(false); parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::Colon, SyntaxKind::Eq]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Const))? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::Colon, None)? { + if parser.find_and_pop( + SyntaxKind::Colon, + ExpectedKind::TypeSpecifier(SyntaxKind::Const), + )? { parser.bump(); parse_type(parser, None)?; } - if parser.find_and_pop( - SyntaxKind::Eq, - Some("expected `=` for const value definition"), - )? { + + parser.set_newline_as_trivia(true); + if parser.find_and_pop(SyntaxKind::Eq, ExpectedKind::Unspecified)? { parser.bump(); parse_expr(parser)?; } @@ -480,7 +506,7 @@ impl super::Parse for ExternScope { parser.bump_expected(SyntaxKind::ExternKw); parser.set_scope_recovery_stack(&[SyntaxKind::LBrace]); - if parser.find(SyntaxKind::LBrace, Some("missing `extern` body"))? { + if parser.find(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Extern))? { parser.parse(ExternItemListScope::default())?; } Ok(()) @@ -505,20 +531,14 @@ impl super::Parse for TypeAliasScope { parser.bump_expected(SyntaxKind::TypeKw); parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::Lt, SyntaxKind::Eq]); - if parser.find_and_pop( - SyntaxKind::Ident, - Some("expected identifier for type alias name"), - )? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::TypeAlias))? { parser.bump(); } parser.pop_recovery_stack(); parse_generic_params_opt(parser, true)?; - if parser.find_and_pop( - SyntaxKind::Eq, - Some("expected `=` for type alias definition"), - )? { + if parser.find_and_pop(SyntaxKind::Eq, ExpectedKind::Unspecified)? { parser.bump(); parse_type(parser, None)?; } @@ -558,7 +578,11 @@ fn parse_fn_item_block( checkpoint.get_or_insert(modifier_checkpoint); } else { while is_modifier(parser.current_kind()) { - parser.unexpected_token_error("modifier is not allowed in this block", None); + let kind = parser.current_kind().unwrap(); + parser.unexpected_token_error(format!( + "{} modifier is not allowed in this block", + kind.describe() + )); } } } @@ -568,10 +592,7 @@ fn parse_fn_item_block( parser.parse_cp(FuncScope::new(fn_def_scope), checkpoint)?; parser.set_newline_as_trivia(false); - parser.expect( - &[SyntaxKind::Newline, SyntaxKind::RBrace], - Some("expected newline after item definition"), - )?; + parser.expect(&[SyntaxKind::Newline, SyntaxKind::RBrace], None)?; } _ => { let proof = parser.error_msg_on_current_token("only `fn` is allowed in this block"); diff --git a/crates/parser2/src/parser/mod.rs b/crates/parser2/src/parser/mod.rs index 5c340d42e..6ca9beff9 100644 --- a/crates/parser2/src/parser/mod.rs +++ b/crates/parser2/src/parser/mod.rs @@ -6,7 +6,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::SmallVec; use self::token_stream::{BackTrackableTokenStream, LexicalToken, TokenStream}; -use crate::{syntax_node::SyntaxNode, GreenNode, ParseError, SyntaxKind, TextRange}; +use crate::{syntax_node::SyntaxNode, ExpectedKind, GreenNode, ParseError, SyntaxKind, TextRange}; pub mod token_stream; @@ -72,36 +72,6 @@ impl Parser { self.peek_non_trivia() } - // xxx doc - pub fn current_token_range(&mut self) -> Option { - let mut start = self.current_pos; - if !self.is_newline_trivia { - for tok in &self.next_trivias { - if tok.syntax_kind() == SyntaxKind::Newline { - return Some(TextRange::new(start, start + tok.text_size())); - } - start += tok.text_size(); - } - } - - while let Some(next) = self.stream.peek().map(|tok| tok.syntax_kind()) { - if self.is_trivia(next) { - let next = self.stream.next().unwrap(); - start += next.text_size(); - - self.next_trivias.push_back(next); - continue; - } else { - return Some(TextRange::new( - start, - start + self.stream.peek().unwrap().text_size(), - )); - } - } - - None - } - /// Returns the current non-trivia token kind of the parser. pub fn current_kind(&mut self) -> Option { self.current_token().map(|tok| tok.syntax_kind()) @@ -150,7 +120,7 @@ impl Parser { Ok(()) } else { let pos = self.current_pos; - let (index, unexpected) = self.recover(None); + let (index, unexpected) = self.recover(); let proof = if unexpected.is_some() { ErrProof(()) } else { @@ -163,11 +133,10 @@ impl Parser { r } - // xxx pub fn expect( &mut self, expected: &[SyntaxKind], - msg: Option<&str>, + kind: Option, ) -> Result<(), Recovery> { let current = self.current_kind(); @@ -179,11 +148,11 @@ impl Parser { Ok(()) } else { let pos = self.current_pos; - let (index, unexpected) = self.recover(None); + let (index, unexpected) = self.recover(); let proof = if unexpected.is_some() { ErrProof(()) } else { - self.add_error(ParseError::expected(expected, msg, pos)) + self.add_error(ParseError::expected(expected, kind, pos)) }; self.pop_recovery_stack(); self.allow_local_recovery(Err(Recovery(index, proof))) @@ -229,10 +198,9 @@ impl Parser { mut scope: T, checkpoint: Option, ) -> Result - // xxx checkpoint handling where T: Parse + 'static, - E: XxxRecoveryThing, + E: Recoverable, { let checkpoint = self.enter(scope.clone(), checkpoint); let start_checkpoint = self.checkpoint(); @@ -245,37 +213,22 @@ impl Parser { pub fn parse(&mut self, scope: T) -> Result<(), E> where T: Parse + 'static, - E: XxxRecoveryThing, + E: Recoverable, { - self.parse_cp(scope, None).map(|_| ()) + self.parse_ok(scope).map(|_| ()) } - // xxx do we ever want to use this? - pub fn parses_without_error(&mut self, mut scope: T) -> bool + pub fn parse_ok(&mut self, mut scope: T) -> Result where T: Parse + 'static, - E: XxxRecoveryThing, - { - debug_assert!(self.is_dry_run()); - let checkpoint = self.enter(scope.clone(), None); - let r = scope.parse(self); - let is_err = self.leave(checkpoint); - r.is_ok() && !is_err - } - - // xxx remove? - pub fn parse_or_recover(&mut self, mut scope: T) -> Result<(), Recovery> - where - T: Parse + 'static, + E: Recoverable, { let checkpoint = self.enter(scope.clone(), None); let res = scope.parse(self); self.leave(checkpoint); - if let Err(err) = res { - let proof = self.add_error(err); - self.try_recover().map_err(|r| r.add_err_proof(proof))?; - } - Ok(()) + let ok = res.is_ok(); + let res = self.allow_local_recovery(res); + res.map(|_| ok) } pub fn or_recover(&mut self, f: F) -> Result<(), Recovery> @@ -301,7 +254,7 @@ impl Parser { if !self.parents.is_empty() { self.bump_trivias(); } - // xxx don't push current scope onto parents stack + self.parents .push(ScopeEntry::new(Box::new(scope), self.is_newline_trivia)); // `is_newline_trivia` is always `true` when entering a scope. @@ -332,10 +285,6 @@ impl Parser { } pub fn add_error(&mut self, err: ParseError) -> ErrProof { - eprintln!( - "add_error: {err:?} {}", - std::backtrace::Backtrace::capture() - ); self.parents.last_mut().unwrap().is_err = true; self.errors.push(err); ErrProof(()) @@ -356,21 +305,6 @@ impl Parser { self.try_recover().map_err(|r| r.add_err_proof(proof)) } - // xxx check uses of error_and_recover - pub fn recover_and_error_if_no_skipped_tokens( - &mut self, - msg: &str, - ) -> Result<(), Recovery> { - let (index, unexpected) = self.recover(None); - if unexpected.is_none() { - self.add_error(ParseError::Msg( - msg.into(), - TextRange::empty(self.current_pos), - )); - } - self.allow_local_recovery(Err(Recovery(index, ErrProof(())))) - } - /// Runs the parser in the dry run mode. /// /// Any changes to the parser state will be reverted. @@ -432,16 +366,16 @@ impl Parser { pub fn find( &mut self, kind: SyntaxKind, - msg: Option<&str>, + err: ExpectedKind, ) -> Result> { self.scope_aux_recovery().push(kind); - self.find_and_pop(kind, msg) + self.find_and_pop(kind, err) } pub fn find_and_pop( &mut self, kind: SyntaxKind, - msg: Option<&str>, + err: ExpectedKind, ) -> Result> { debug_assert_eq!(self.scope_aux_recovery().last(), Some(&kind)); @@ -453,7 +387,7 @@ impl Parser { if self.current_kind() == Some(kind) { Ok(true) } else { - let proof = self.add_error(ParseError::expected(&[kind], msg, pos)); + let proof = self.add_error(ParseError::expected(&[kind], Some(err), pos)); r.map(|_| false).map_err(|rec| rec.add_err_proof(proof)) } }; @@ -462,26 +396,15 @@ impl Parser { } pub fn try_recover(&mut self) -> Result<(), Recovery<()>> { - let (index, _) = self.recover(None); + let (index, _) = self.recover(); self.allow_local_recovery(Err(Recovery(index, ()))) } - // xxx remove checkpoint arg? /// Consumes tokens until a recovery token is found, and reports an error on any /// unexpected tokens. - /// Returns the index of the scope that matched the recovery token. - fn recover( - &mut self, - checkpoint: Option, - ) -> (Option, Option) { - if !self.is_dry_run() { - eprintln!( - "recover! {:?} {:?} scopes: {:#?}", - self.current_kind(), - self.current_token().map(|t| t.text().to_string()), - self.parents - ); - } + /// Returns the index of the scope that matched the recovery token, + /// and the total string length of the unexpected tokens. + fn recover(&mut self) -> (Option, Option) { let mut unexpected = None; let mut open_brackets_in_error = FxHashMap::default(); let mut match_scope_index = None; @@ -502,12 +425,6 @@ impl Parser { .find(|(_i, scope)| scope.is_recovery_match(kind)) { match_scope_index = Some(scope_index); - if !self.is_dry_run() { - eprintln!( - "recovered at {scope_index} on {kind:?}, {:#?}", - self.parents[scope_index] - ); - } break; } @@ -515,16 +432,7 @@ impl Parser { if !self.parents.is_empty() { self.bump_trivias(); } - unexpected = Some(( - self.current_pos, - checkpoint.unwrap_or_else(|| self.checkpoint()), - )); - } - if !self.is_dry_run() { - eprintln!( - "skipping {kind:?} {:?}", - self.current_token().unwrap().text() - ); + unexpected = Some((self.current_pos, self.checkpoint())); } self.bump(); } @@ -535,22 +443,23 @@ impl Parser { .start_node_at(checkpoint, SyntaxKind::Error.into()); self.builder.finish_node(); - self.add_error(ParseError::Unexpected(TextRange::new( - start_pos, - self.current_pos, - ))); + self.add_error(ParseError::Unexpected( + format!( + "unexpected syntax while parsing {}", + self.parents.last().unwrap().scope.syntax_kind().describe() + ), + TextRange::new(start_pos, self.current_pos), + )); } } - eprintln!("{}", std::backtrace::Backtrace::capture()); ( match_scope_index.map(ScopeIndex), unexpected.map(|(start_pos, _)| start_pos), ) } - // xxx - fn allow_local_recovery(&self, r: Result<(), E>) -> Result<(), E> { + fn allow_local_recovery(&self, r: Result<(), E>) -> Result<(), E> { match r { Ok(()) => Ok(()), Err(e) if e.is_local_recovery(self) => Ok(()), @@ -689,16 +598,15 @@ impl Parser { self.add_error(ParseError::Msg(msg.into(), TextRange::new(start, end))) } - // xxx remove this or error_msg_on_current_token - /// Wrap the current token in a `SyntaxKind::Error`, and add `msg` to the error list. - fn unexpected_token_error(&mut self, msg: &str, checkpoint: Option) { - let checkpoint = self.enter(ErrorScope::default(), checkpoint); + /// Wrap the current token in a `SyntaxKind::Error`, and add a `ParseError::Unexpected`. + fn unexpected_token_error(&mut self, msg: String) { + let checkpoint = self.enter(ErrorScope::default(), None); let start_pos = self.current_pos; self.bump(); - self.add_error(ParseError::Msg( - msg.into(), + self.add_error(ParseError::Unexpected( + msg, TextRange::new(start_pos, self.current_pos), )); self.leave(checkpoint); @@ -755,14 +663,14 @@ impl From> for Recovery<()> { } } -pub trait XxxRecoveryThing { +pub trait Recoverable { fn is_local_recovery(&self, _parser: &Parser) -> bool { false } } -impl XxxRecoveryThing for ParseError {} -impl XxxRecoveryThing for Infallible {} -impl XxxRecoveryThing for Recovery { +impl Recoverable for ParseError {} +impl Recoverable for Infallible {} +impl Recoverable for Recovery { fn is_local_recovery(&self, parser: &Parser) -> bool { self.0 .as_ref() @@ -964,12 +872,12 @@ use define_scope; #[doc(hidden)] use define_scope_struct; -// xxx move /// Parse a comma-separated list of elements, with trailing commas allowed. /// Panics if `parser.current_kind() != Some(brackets.0)` fn parse_list( parser: &mut Parser, newline_delim: bool, + list_kind: SyntaxKind, brackets: (SyntaxKind, SyntaxKind), element: F, ) -> Result<(), Recovery> @@ -978,13 +886,18 @@ where { parser.bump_expected(brackets.0); + let expected_closing_bracket = Some(ExpectedKind::ClosingBracket { + bracket: brackets.1, + parent: list_kind, + }); + loop { if parser.bump_if(brackets.1) { return Ok(()); } + element(parser)?; - dbg!(parser.current_token().map(|t| t.text().to_string())); if parser.current_kind() != Some(SyntaxKind::Comma) && parser.current_kind() != Some(brackets.1) { @@ -993,13 +906,12 @@ where let newline = parser.current_kind() == Some(SyntaxKind::Newline) || { parser.with_recovery_tokens( |parser| { - // xxx clean let pos = parser.current_pos; - let (index, unexpected) = parser.recover(None); + let (index, unexpected) = parser.recover(); if unexpected.is_none() { parser.add_error(ParseError::expected( &[brackets.1, SyntaxKind::Comma], - None, + expected_closing_bracket, pos, )); } @@ -1012,24 +924,22 @@ where parser.set_newline_as_trivia(nt); if newline { - dbg!(newline_delim); parser.add_error(ParseError::expected( &[brackets.1, SyntaxKind::Comma], - None, + expected_closing_bracket, parser.current_pos, )); if !newline_delim { return Ok(()); } } else { - parser.expect(&[brackets.1, SyntaxKind::Comma], None)?; + parser.expect(&[brackets.1, SyntaxKind::Comma], expected_closing_bracket)?; if !parser.bump_if(SyntaxKind::Comma) { break; } } } else if !parser.bump_if(SyntaxKind::Comma) { - dbg!("2", parser.current_kind()); - parser.expect(&[brackets.1], None)?; + parser.expect(&[brackets.1], expected_closing_bracket)?; break; } } diff --git a/crates/parser2/src/parser/param.rs b/crates/parser2/src/parser/param.rs index 10af88976..7d79e78a4 100644 --- a/crates/parser2/src/parser/param.rs +++ b/crates/parser2/src/parser/param.rs @@ -1,6 +1,6 @@ use std::convert::Infallible; -use crate::{ParseError, SyntaxKind}; +use crate::{ExpectedKind, ParseError, SyntaxKind}; use super::{ define_scope, @@ -25,6 +25,7 @@ impl super::Parse for FuncParamListScope { parse_list( parser, false, + SyntaxKind::FuncParamList, (SyntaxKind::LParen, SyntaxKind::RParen), |parser| parser.parse(FnParamScope::new(self.allow_self)), ) @@ -72,7 +73,7 @@ impl super::Parse for FnParamScope { } if parser.find( SyntaxKind::Colon, - Some("missing type bound for fn parameter"), + ExpectedKind::TypeSpecifier(SyntaxKind::FnParam), )? { parser.bump(); parse_type(parser, None)?; @@ -93,20 +94,26 @@ impl super::Parse for GenericParamListScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - parse_list(parser, false, (SyntaxKind::Lt, SyntaxKind::Gt), |parser| { - parser.expect( - &[SyntaxKind::Ident, SyntaxKind::ConstKw, SyntaxKind::Gt], - None, - )?; - match parser.current_kind() { - Some(SyntaxKind::ConstKw) => parser.parse(ConstGenericParamScope::default()), - Some(SyntaxKind::Ident) => { - parser.parse(TypeGenericParamScope::new(self.disallow_trait_bound)) + parse_list( + parser, + false, + SyntaxKind::GenericParamList, + (SyntaxKind::Lt, SyntaxKind::Gt), + |parser| { + parser.expect( + &[SyntaxKind::Ident, SyntaxKind::ConstKw, SyntaxKind::Gt], + None, + )?; + match parser.current_kind() { + Some(SyntaxKind::ConstKw) => parser.parse(ConstGenericParamScope::default()), + Some(SyntaxKind::Ident) => { + parser.parse(TypeGenericParamScope::new(self.disallow_trait_bound)) + } + Some(SyntaxKind::Gt) => Ok(()), + _ => unreachable!(), } - Some(SyntaxKind::Gt) => Ok(()), - _ => unreachable!(), - } - }) + }, + ) } } @@ -123,10 +130,16 @@ impl super::Parse for ConstGenericParamScope { parser.bump_expected(SyntaxKind::ConstKw); parser.set_scope_recovery_stack(&[SyntaxKind::Ident, SyntaxKind::Colon]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop( + SyntaxKind::Ident, + ExpectedKind::Name(SyntaxKind::ConstGenericParam), + )? { parser.bump(); } - if parser.find_and_pop(SyntaxKind::Colon, None)? { + if parser.find_and_pop( + SyntaxKind::Colon, + ExpectedKind::TypeSpecifier(SyntaxKind::ConstGenericParam), + )? { parser.bump(); parse_type(parser, None)?; } @@ -211,7 +224,13 @@ fn parse_kind_bound(parser: &mut Parser) -> Result<(), Recove if parser.bump_if(SyntaxKind::LParen) { parse_kind_bound(parser)?; - if parser.find(SyntaxKind::RParen, None)? { + if parser.find( + SyntaxKind::RParen, + ExpectedKind::ClosingBracket { + bracket: SyntaxKind::RParen, + parent: SyntaxKind::TypeBound, + }, + )? { parser.bump(); } } else if parser.current_kind() == Some(SyntaxKind::Star) { @@ -266,10 +285,9 @@ impl super::Parse for TraitRefScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - // xxx add test that triggers this parser.or_recover(|parser| { parser.parse(PathScope::default()).map_err(|_| { - ParseError::expected(&[SyntaxKind::TraitRef], None, parser.current_pos) + ParseError::expected(&[SyntaxKind::TraitRef], None, parser.end_of_prev_token) }) })?; @@ -289,9 +307,13 @@ impl super::Parse for GenericArgListScope { type Error = Recovery; fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { - parse_list(parser, false, (SyntaxKind::Lt, SyntaxKind::Gt), |parser| { - parser.parse(GenericArgScope::default()) - }) + parse_list( + parser, + false, + SyntaxKind::GenericArgList, + (SyntaxKind::Lt, SyntaxKind::Gt), + |parser| parser.parse(GenericArgScope::default()), + ) } } @@ -335,6 +357,7 @@ impl super::Parse for CallArgListScope { parse_list( parser, false, + SyntaxKind::CallArgList, (SyntaxKind::LParen, SyntaxKind::RParen), |parser| parser.parse(CallArgScope::default()), ) @@ -379,27 +402,34 @@ impl super::Parse for WhereClauseScope { _ => break, } - if !parser.bump_if(SyntaxKind::Comma) { - if parser.current_kind().is_some() && is_type_start(parser.current_kind().unwrap()) - { - parser.set_newline_as_trivia(false); - let newline = parser.current_kind() == Some(SyntaxKind::Newline); - parser.set_newline_as_trivia(true); - - if newline { - parser.add_error(ParseError::expected( - &[SyntaxKind::Comma], - None, - parser.current_pos, - )); - } else if parser.find(SyntaxKind::Comma, None)? { - parser.bump(); - } else { - break; - } + if !parser.bump_if(SyntaxKind::Comma) + && parser.current_kind().is_some() + && is_type_start(parser.current_kind().unwrap()) + { + parser.set_newline_as_trivia(false); + let newline = parser.current_kind() == Some(SyntaxKind::Newline); + parser.set_newline_as_trivia(true); + + if newline { + parser.add_error(ParseError::expected( + &[SyntaxKind::Comma], + None, + parser.current_pos, + )); + } else if parser.find( + SyntaxKind::Comma, + ExpectedKind::Separator { + separator: SyntaxKind::Comma, + element: SyntaxKind::WherePredicate, + }, + )? { + parser.bump(); + } else { + break; } } } + if pred_count == 0 { parser.error("`where` clause requires one or more type constraints"); } @@ -419,8 +449,8 @@ impl super::Parse for WherePredicateScope { } else { parser.add_error(ParseError::expected( &[SyntaxKind::Colon], - Some("missing type bound in `where` clause"), - parser.current_pos, + Some(ExpectedKind::TypeSpecifier(SyntaxKind::WherePredicate)), + parser.end_of_prev_token, )); } Ok(()) diff --git a/crates/parser2/src/parser/pat.rs b/crates/parser2/src/parser/pat.rs index 3cb964f98..709a5419f 100644 --- a/crates/parser2/src/parser/pat.rs +++ b/crates/parser2/src/parser/pat.rs @@ -106,6 +106,7 @@ impl super::Parse for TuplePatElemListScope { parse_list( parser, false, + SyntaxKind::TuplePatElemList, (SyntaxKind::LParen, SyntaxKind::RParen), parse_pat, ) @@ -118,13 +119,8 @@ impl super::Parse for PathPatScope { fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { parser.or_recover(|p| { - p.parse(PathScope::default()).map_err(|e| { - ParseError::expected( - &[SyntaxKind::PathPat], - Some("expected a pattern"), - e.range().start(), - ) - }) + p.parse(PathScope::default()) + .map_err(|e| ParseError::expected(&[SyntaxKind::PathPat], None, e.range().start())) })?; parser.set_newline_as_trivia(false); @@ -148,6 +144,7 @@ impl super::Parse for RecordPatFieldListScope { parse_list( parser, true, + SyntaxKind::RecordPatFieldList, (SyntaxKind::LBrace, SyntaxKind::RBrace), |parser| parser.parse(RecordPatFieldScope::default()), ) diff --git a/crates/parser2/src/parser/path.rs b/crates/parser2/src/parser/path.rs index 8ed45ce55..60751afe5 100644 --- a/crates/parser2/src/parser/path.rs +++ b/crates/parser2/src/parser/path.rs @@ -38,7 +38,7 @@ impl super::Parse for PathSegmentScope { _ => Err(ParseError::expected( &[SyntaxKind::PathSegment], None, - parser.current_pos, + parser.end_of_prev_token, )), } } diff --git a/crates/parser2/src/parser/stmt.rs b/crates/parser2/src/parser/stmt.rs index affd4c8ba..ff134db01 100644 --- a/crates/parser2/src/parser/stmt.rs +++ b/crates/parser2/src/parser/stmt.rs @@ -1,6 +1,6 @@ use std::convert::Infallible; -use crate::SyntaxKind; +use crate::{ExpectedKind, SyntaxKind}; use super::{ define_scope, @@ -37,7 +37,7 @@ impl super::Parse for LetStmtScope { fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { parser.bump_expected(SyntaxKind::LetKw); parser.set_newline_as_trivia(false); - parse_pat(parser)?; // xxx "expected pattern" error msg + parse_pat(parser)?; if parser.current_kind() == Some(SyntaxKind::Colon) { parser.bump_expected(SyntaxKind::Colon); @@ -58,15 +58,18 @@ impl super::Parse for ForStmtScope { fn parse(&mut self, parser: &mut Parser) -> Result<(), Self::Error> { parser.bump_expected(SyntaxKind::ForKw); - parser.set_scope_recovery_stack(&[SyntaxKind::InKw, SyntaxKind::LBrace]); + parser.set_scope_recovery_stack(&[SyntaxKind::InKw, SyntaxKind::Ident, SyntaxKind::LBrace]); parse_pat(parser)?; - if parser.find_and_pop(SyntaxKind::InKw, None)? { + if parser.find_and_pop(SyntaxKind::InKw, ExpectedKind::Unspecified)? { parser.bump(); } parse_expr_no_struct(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, None)? { + // pop `Ident` recovery token, which is only included because it solves a contrived test case + parser.pop_recovery_stack(); + + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::ForStmt))? { parser.parse(BlockExprScope::default())?; } Ok(()) @@ -83,7 +86,10 @@ impl super::Parse for WhileStmtScope { parser.set_scope_recovery_stack(&[SyntaxKind::LBrace]); parse_expr_no_struct(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, None)? { + if parser.find_and_pop( + SyntaxKind::LBrace, + ExpectedKind::Body(SyntaxKind::WhileStmt), + )? { parser.parse(BlockExprScope::default())?; } Ok(()) diff --git a/crates/parser2/src/parser/struct_.rs b/crates/parser2/src/parser/struct_.rs index c958c5076..962039eda 100644 --- a/crates/parser2/src/parser/struct_.rs +++ b/crates/parser2/src/parser/struct_.rs @@ -1,4 +1,4 @@ -use crate::SyntaxKind; +use crate::{ExpectedKind, SyntaxKind}; use super::{ attr::parse_attr_list, @@ -29,7 +29,7 @@ impl super::Parse for StructScope { SyntaxKind::LBrace, ]); - if parser.find_and_pop(SyntaxKind::Ident, None)? { + if parser.find_and_pop(SyntaxKind::Ident, ExpectedKind::Name(SyntaxKind::Struct))? { parser.bump(); } @@ -39,7 +39,7 @@ impl super::Parse for StructScope { parser.expect_and_pop_recovery_stack()?; parse_where_clause_opt(parser)?; - if parser.find_and_pop(SyntaxKind::LBrace, Some("struct field definition"))? { + if parser.find_and_pop(SyntaxKind::LBrace, ExpectedKind::Body(SyntaxKind::Struct))? { parser.parse(RecordFieldDefListScope::default())?; } Ok(()) @@ -62,6 +62,7 @@ impl super::Parse for RecordFieldDefListScope { parse_list( parser, true, + SyntaxKind::RecordFieldDefList, (SyntaxKind::LBrace, SyntaxKind::RBrace), |parser| parser.parse(RecordFieldDefScope::default()), ) @@ -99,11 +100,17 @@ impl super::Parse for RecordFieldDefScope { parser.set_scope_recovery_stack(&[SyntaxKind::Colon]); - if parser.find(SyntaxKind::Ident, Some("expected a field name"))? { + if parser.find( + SyntaxKind::Ident, + ExpectedKind::Name(SyntaxKind::RecordField), + )? { parser.bump(); } - if parser.find(SyntaxKind::Colon, Some("missing field type"))? { + if parser.find( + SyntaxKind::Colon, + ExpectedKind::TypeSpecifier(SyntaxKind::RecordField), + )? { parser.bump(); parse_type(parser, None).map(|_| ())?; } diff --git a/crates/parser2/src/parser/type_.rs b/crates/parser2/src/parser/type_.rs index 1f05ffa8a..e09eb0f88 100644 --- a/crates/parser2/src/parser/type_.rs +++ b/crates/parser2/src/parser/type_.rs @@ -1,4 +1,4 @@ -use crate::{ParseError, SyntaxKind}; +use crate::{ExpectedKind, ParseError, SyntaxKind}; use super::{ define_scope, @@ -89,6 +89,7 @@ impl super::Parse for TupleTypeScope { parse_list( parser, false, + SyntaxKind::TupleType, (SyntaxKind::LParen, SyntaxKind::RParen), |parser| { parse_type(parser, None)?; @@ -114,13 +115,19 @@ impl super::Parse for ArrayTypeScope { parse_type(parser, None)?; - if parser.find_and_pop(SyntaxKind::SemiColon, None)? { + if parser.find_and_pop(SyntaxKind::SemiColon, ExpectedKind::Unspecified)? { parser.bump(); } parse_expr(parser)?; - if parser.find_and_pop(SyntaxKind::RBracket, None)? { + if parser.find_and_pop( + SyntaxKind::RBracket, + ExpectedKind::ClosingBracket { + bracket: SyntaxKind::RBracket, + parent: SyntaxKind::ArrayType, + }, + )? { parser.bump(); } Ok(()) diff --git a/crates/parser2/src/parser/use_tree.rs b/crates/parser2/src/parser/use_tree.rs index 7302fca0f..9e9c60b5c 100644 --- a/crates/parser2/src/parser/use_tree.rs +++ b/crates/parser2/src/parser/use_tree.rs @@ -1,4 +1,4 @@ -use std::{cell::Cell, rc::Rc}; +use std::{cell::Cell, convert::identity, rc::Rc}; use crate::{parser::path::is_path_segment, ParseError, SyntaxKind, TextRange}; @@ -19,7 +19,7 @@ impl super::Parse for UseTreeScope { } let use_path_scope = UsePathScope::default(); - parser.parse_or_recover(use_path_scope.clone())?; + parser.or_recover(|p| p.parse(use_path_scope.clone()))?; let is_glob = use_path_scope.is_glob.get(); if parser.current_kind() == Some(SyntaxKind::AsKw) { @@ -27,7 +27,7 @@ impl super::Parse for UseTreeScope { parser.error_msg_on_current_token("can't use `as` with `*`"); } if parser.current_kind() == Some(SyntaxKind::AsKw) { - parser.parse_or_recover(UseTreeAliasScope::default())?; + parser.or_recover(|p| p.parse(UseTreeAliasScope::default()))?; } return Ok(()); } @@ -57,6 +57,7 @@ impl super::Parse for UseTreeListScope { parse_list( parser, true, + SyntaxKind::UseTreeList, (SyntaxKind::LBrace, SyntaxKind::RBrace), |parser| parser.parse(UseTreeScope::default()), ) @@ -78,7 +79,9 @@ impl super::Parse for UsePathScope { loop { let is_path_segment = parser.dry_run(|parser| { parser.bump_if(SyntaxKind::Colon2) - && parser.parses_without_error(UsePathSegmentScope::default()) + && parser + .parse_ok(UsePathSegmentScope::default()) + .is_ok_and(identity) }); if is_path_segment { if self.is_glob.get() { @@ -112,7 +115,7 @@ impl super::Parse for UsePathSegmentScope { _ => { return Err(ParseError::Msg( "expected identifier or `self`".into(), - TextRange::empty(parser.current_pos), + TextRange::empty(parser.end_of_prev_token), )); } } diff --git a/crates/parser2/src/syntax_kind.rs b/crates/parser2/src/syntax_kind.rs index cf97d6ab8..a1e9bb16b 100644 --- a/crates/parser2/src/syntax_kind.rs +++ b/crates/parser2/src/syntax_kind.rs @@ -520,8 +520,6 @@ impl SyntaxKind { ) } - // xxx - /// Panics if `self` is not a token kind pub fn describe(self) -> &'static str { match self { SyntaxKind::Newline => "newline", @@ -559,9 +557,9 @@ impl SyntaxKind { SyntaxKind::Pipe2 => "`||`", SyntaxKind::Lt => "`<`", SyntaxKind::Gt => "`>`", - SyntaxKind::Eq => "``", - SyntaxKind::Eq2 => "``", - SyntaxKind::NotEq => "``", + SyntaxKind::Eq => "`=`", + SyntaxKind::Eq2 => "`==`", + SyntaxKind::NotEq => "`!=`", SyntaxKind::AsKw => "`as`", SyntaxKind::TrueKw => "`true`", SyntaxKind::FalseKw => "`false`", @@ -599,13 +597,198 @@ impl SyntaxKind { SyntaxKind::LtEq => "`<=`", SyntaxKind::GtEq => "`>=`", - SyntaxKind::PathType => "a type name", - SyntaxKind::TraitRef => "a trait name", - SyntaxKind::PathSegment => "a path segment", - SyntaxKind::PathPat => "a pattern", - _ => unimplemented!(), + SyntaxKind::PathType => "type", + SyntaxKind::TraitRef => "trait name", + SyntaxKind::PathSegment => "path segment", + SyntaxKind::PathPat => "pattern", + + SyntaxKind::ArrayExpr => "array definition", + SyntaxKind::RecordFieldDef => "field", + SyntaxKind::IndexExpr => "index expression", + SyntaxKind::BlockExpr => "block", + SyntaxKind::TypeBound => "type bound", + SyntaxKind::CallArgList => "function call arguments", + + SyntaxKind::InvalidToken => unimplemented!(), + SyntaxKind::WhiteSpace => "whitespace", + SyntaxKind::Comment => "comment", + SyntaxKind::DocComment => "doc comment", + + SyntaxKind::Lit => "literal", + SyntaxKind::BinExpr => "binary expression", + SyntaxKind::UnExpr => "unary expression", + SyntaxKind::CallExpr => "function call expression", + SyntaxKind::CallArg => "function call argument", + SyntaxKind::MethodCallExpr => "method call expression", + SyntaxKind::GenericArgList => "generic type argument list", + SyntaxKind::TypeGenericArg => "generic type argument", + SyntaxKind::ConstGenericArg => "generic const argument", + SyntaxKind::PathExpr => "path", + SyntaxKind::RecordInitExpr => "record initialization expression", + SyntaxKind::RecordFieldList => "record field list", + SyntaxKind::RecordField => "field", + SyntaxKind::FieldExpr => "field", + SyntaxKind::TupleExpr => "tuple expression", + SyntaxKind::ArrayRepExpr => "array expression", + SyntaxKind::LitExpr => "literal expression", + SyntaxKind::IfExpr => "`if` expression", + SyntaxKind::MatchExpr => "`match` expression", + SyntaxKind::ParenExpr => "parenthesized expression", + SyntaxKind::AssignExpr => "assignment expression", + SyntaxKind::AugAssignExpr => "augmented assignment expression", + SyntaxKind::LetStmt => "`let` statement", + SyntaxKind::ForStmt => "`for` statement", + SyntaxKind::WhileStmt => "`while` statement", + SyntaxKind::ContinueStmt => "`continue` statement", + SyntaxKind::BreakStmt => "`break` statement", + SyntaxKind::ReturnStmt => "`return` statement", + SyntaxKind::ExprStmt => "`expr` statement", + SyntaxKind::WildCardPat => "wildcard pattern", + SyntaxKind::RestPat => "`..` pattern", + SyntaxKind::LitPat => "literal pattern", + SyntaxKind::TuplePat => "tuple pattern", + SyntaxKind::TuplePatElemList => "tuple pattern element list", + SyntaxKind::PathTuplePat => "path tuple pattern", + SyntaxKind::RecordPat => "record pattern", + SyntaxKind::RecordPatFieldList => "record pattern field list", + SyntaxKind::RecordPatField => "record pattern field", + SyntaxKind::OrPat => "`or` pattern", + SyntaxKind::MatchArm => "`match` arm", + SyntaxKind::MatchArmList => "`match` arm list", + SyntaxKind::Item => "item", + SyntaxKind::Mod => "`mod`", + SyntaxKind::Func => "function definition", + SyntaxKind::Struct => "struct definition", + SyntaxKind::Contract => "contract definition", + SyntaxKind::Enum => "enum definition", + SyntaxKind::TypeAlias => "type alias", + SyntaxKind::Impl => "`impl` block", + SyntaxKind::ImplItemList => "`impl` item list", + SyntaxKind::Trait => "trait definition", + SyntaxKind::SuperTraitList => "supertrait list", + SyntaxKind::TraitItemList => "`trait` item list", + SyntaxKind::ImplTrait => "`impl` trait block", + SyntaxKind::ImplTraitItemList => "`impl` trait item list", + SyntaxKind::Const => "const definition", + SyntaxKind::Use => "`use` statement", + SyntaxKind::UseTree => "`use` tree", + SyntaxKind::UseTreeList => "`use` tree list", + SyntaxKind::UsePath => "`use` path", + SyntaxKind::UsePathSegment => "`use` path segment", + SyntaxKind::UseTreeRename => "`use as` rename", + SyntaxKind::Extern => "`extern` block", + SyntaxKind::ExternItemList => "`extern` body", + SyntaxKind::ItemList => "item list", + SyntaxKind::ItemModifier => "item modifier", + SyntaxKind::PtrType => "pointer type", + SyntaxKind::SelfType => "`Self` type", + SyntaxKind::TupleType => "tuple type definition", + SyntaxKind::ArrayType => "array type definition", + SyntaxKind::Path => "path", + SyntaxKind::Attr => "attribute", + SyntaxKind::AttrArgList => "attribute argument list", + SyntaxKind::AttrArg => "attribute argument", + SyntaxKind::DocCommentAttr => "doc comment", + SyntaxKind::AttrList => "attribute list", + SyntaxKind::Visibility => "visibility modifier", + SyntaxKind::RecordFieldDefList => "record field list", + SyntaxKind::VariantDef => "`enum` variant definition", + SyntaxKind::VariantDefList => "`enum` variant list", + SyntaxKind::TypeGenericParam => "generic type parameter", + SyntaxKind::ConstGenericParam => "constant generic parameter", + SyntaxKind::GenericParamList => "generic parameter list", + SyntaxKind::FuncSignature => "function signature", + SyntaxKind::FuncParamList => "function parameter list", + SyntaxKind::FnParam => "function parameter", + SyntaxKind::TypeBoundList => "type bound list", + SyntaxKind::KindBoundAbs => "kind bound", + SyntaxKind::KindBoundMono => "kind bound", + SyntaxKind::WhereClause => "`where` clause", + SyntaxKind::WherePredicate => "`where` predicate", + SyntaxKind::Root => todo!(), + SyntaxKind::Error => todo!(), } } + + pub fn is_token(self) -> bool { + matches!( + self, + SyntaxKind::Newline + | SyntaxKind::Ident + | SyntaxKind::Int + | SyntaxKind::String + | SyntaxKind::LParen + | SyntaxKind::RParen + | SyntaxKind::LBrace + | SyntaxKind::RBrace + | SyntaxKind::LBracket + | SyntaxKind::RBracket + | SyntaxKind::Colon + | SyntaxKind::Colon2 + | SyntaxKind::SemiColon + | SyntaxKind::Dot + | SyntaxKind::Dot2 + | SyntaxKind::Comma + | SyntaxKind::Arrow + | SyntaxKind::FatArrow + | SyntaxKind::Underscore + | SyntaxKind::Pound + | SyntaxKind::Plus + | SyntaxKind::Minus + | SyntaxKind::Star + | SyntaxKind::Star2 + | SyntaxKind::Slash + | SyntaxKind::Percent + | SyntaxKind::Tilde + | SyntaxKind::Not + | SyntaxKind::Hat + | SyntaxKind::Amp + | SyntaxKind::Amp2 + | SyntaxKind::Pipe + | SyntaxKind::Pipe2 + | SyntaxKind::Lt + | SyntaxKind::Gt + | SyntaxKind::Eq + | SyntaxKind::Eq2 + | SyntaxKind::NotEq + | SyntaxKind::AsKw + | SyntaxKind::TrueKw + | SyntaxKind::FalseKw + | SyntaxKind::BreakKw + | SyntaxKind::ContinueKw + | SyntaxKind::ContractKw + | SyntaxKind::FnKw + | SyntaxKind::ModKw + | SyntaxKind::ConstKw + | SyntaxKind::IfKw + | SyntaxKind::ElseKw + | SyntaxKind::MatchKw + | SyntaxKind::ForKw + | SyntaxKind::InKw + | SyntaxKind::WhereKw + | SyntaxKind::WhileKw + | SyntaxKind::PubKw + | SyntaxKind::ReturnKw + | SyntaxKind::SelfKw + | SyntaxKind::SelfTypeKw + | SyntaxKind::StructKw + | SyntaxKind::EnumKw + | SyntaxKind::TraitKw + | SyntaxKind::ImplKw + | SyntaxKind::TypeKw + | SyntaxKind::LetKw + | SyntaxKind::MutKw + | SyntaxKind::UseKw + | SyntaxKind::ExternKw + | SyntaxKind::UnsafeKw + | SyntaxKind::IngotKw + | SyntaxKind::SuperKw + | SyntaxKind::LShift + | SyntaxKind::RShift + | SyntaxKind::LtEq + | SyntaxKind::GtEq + ) + } } impl From for rowan::SyntaxKind { diff --git a/crates/parser2/test_files/error_recovery/items/const_.snap b/crates/parser2/test_files/error_recovery/items/const_.snap index a82e34328..04dc26dce 100644 --- a/crates/parser2/test_files/error_recovery/items/const_.snap +++ b/crates/parser2/test_files/error_recovery/items/const_.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/const_.fe --- Root@0..44 ItemList@0..44 - Item@0..14 + Item@0..12 Const@0..12 ConstKw@0..5 "const" WhiteSpace@5..6 " " @@ -16,9 +16,9 @@ Root@0..44 LitExpr@10..12 Lit@10..12 Int@10..12 "10" - Newline@12..14 "\n\n" - Item@14..29 - Const@14..29 + Newline@12..14 "\n\n" + Item@14..26 + Const@14..26 ConstKw@14..19 "const" WhiteSpace@19..20 " " Ident@20..21 "X" @@ -28,9 +28,8 @@ Root@0..44 Path@23..26 PathSegment@23..26 Ident@23..26 "i32" - WhiteSpace@26..27 " " - Error@27..29 - Newline@27..29 "\n\n" + WhiteSpace@26..27 " " + Newline@27..29 "\n\n" Item@29..44 Const@29..44 ConstKw@29..34 "const" diff --git a/crates/parser2/test_files/error_recovery/items/enum_.snap b/crates/parser2/test_files/error_recovery/items/enum_.snap index 968cd001f..3b0e168ce 100644 --- a/crates/parser2/test_files/error_recovery/items/enum_.snap +++ b/crates/parser2/test_files/error_recovery/items/enum_.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/error_recovery/items/enum_.fe --- Root@0..150 - ItemList@0..150 - Item@0..65 + ItemList@0..149 + Item@0..63 Enum@0..63 ItemModifier@0..3 PubKw@0..3 "pub" @@ -67,8 +67,8 @@ Root@0..150 Ident@60..61 "Z" Newline@61..62 "\n" RBrace@62..63 "}" - Newline@63..65 "\n\n" - Item@65..150 + Newline@63..65 "\n\n" + Item@65..149 Enum@65..149 ItemModifier@65..68 PubKw@65..68 "pub" @@ -160,5 +160,5 @@ Root@0..150 RParen@146..147 ")" Newline@147..148 "\n" RBrace@148..149 "}" - Newline@149..150 "\n" + Newline@149..150 "\n" diff --git a/crates/parser2/test_files/error_recovery/items/func.snap b/crates/parser2/test_files/error_recovery/items/func.snap index af1583e0a..30d836c5a 100644 --- a/crates/parser2/test_files/error_recovery/items/func.snap +++ b/crates/parser2/test_files/error_recovery/items/func.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/error_recovery/items/func.fe --- Root@0..133 - ItemList@0..133 - Item@0..80 + ItemList@0..132 + Item@0..78 Func@0..78 FnKw@0..2 "fn" WhiteSpace@2..3 " " @@ -95,8 +95,8 @@ Root@0..133 LBrace@74..75 "{" Newline@75..77 "\n\n" RBrace@77..78 "}" - Newline@78..80 "\n\n" - Item@80..133 + Newline@78..80 "\n\n" + Item@80..132 Func@80..132 FnKw@80..82 "fn" WhiteSpace@82..83 " " @@ -152,5 +152,5 @@ Root@0..133 LBrace@128..129 "{" Newline@129..131 "\n\n" RBrace@131..132 "}" - Newline@132..133 "\n" + Newline@132..133 "\n" diff --git a/crates/parser2/test_files/error_recovery/items/impl_.snap b/crates/parser2/test_files/error_recovery/items/impl_.snap index fc151f4e6..131376c4b 100644 --- a/crates/parser2/test_files/error_recovery/items/impl_.snap +++ b/crates/parser2/test_files/error_recovery/items/impl_.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/impl_.fe --- Root@0..56 ItemList@0..56 - Item@0..39 + Item@0..37 Impl@0..37 ImplKw@0..4 "impl" WhiteSpace@4..5 " " @@ -49,7 +49,7 @@ Root@0..56 LBrace@34..35 "{" WhiteSpace@35..36 " " RBrace@36..37 "}" - Newline@37..39 "\n\n" + Newline@37..39 "\n\n" Item@39..56 Impl@39..56 ImplKw@39..43 "impl" diff --git a/crates/parser2/test_files/error_recovery/items/impl_trait.snap b/crates/parser2/test_files/error_recovery/items/impl_trait.snap index ca96ad858..5e30b5159 100644 --- a/crates/parser2/test_files/error_recovery/items/impl_trait.snap +++ b/crates/parser2/test_files/error_recovery/items/impl_trait.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/impl_trait.fe --- Root@0..90 ItemList@0..90 - Item@0..38 + Item@0..36 ImplTrait@0..36 ImplKw@0..4 "impl" WhiteSpace@4..5 " " @@ -66,8 +66,8 @@ Root@0..90 ImplTraitItemList@34..36 LBrace@34..35 "{" RBrace@35..36 "}" - Newline@36..38 "\n\n" - Item@38..73 + Newline@36..38 "\n\n" + Item@38..71 ImplTrait@38..71 ImplKw@38..42 "impl" WhiteSpace@42..43 " " @@ -124,24 +124,27 @@ Root@0..90 ImplTraitItemList@69..71 LBrace@69..70 "{" RBrace@70..71 "}" - Newline@71..73 "\n\n" + Newline@71..73 "\n\n" Item@73..90 - Impl@73..81 + ImplTrait@73..90 ImplKw@73..77 "impl" WhiteSpace@77..78 " " - PathType@78..79 + TraitRef@78..79 Path@78..79 PathSegment@78..79 Ident@78..79 "E" WhiteSpace@79..80 " " Error@80..81 InvalidToken@80..81 "@" - WhiteSpace@81..82 " " - Error@82..90 + WhiteSpace@81..82 " " ForKw@82..85 "for" WhiteSpace@85..86 " " - Ident@86..87 "F" + PathType@86..87 + Path@86..87 + PathSegment@86..87 + Ident@86..87 "F" WhiteSpace@87..88 " " - LBrace@88..89 "{" - RBrace@89..90 "}" + ImplTraitItemList@88..90 + LBrace@88..89 "{" + RBrace@89..90 "}" diff --git a/crates/parser2/test_files/error_recovery/items/struct_.snap b/crates/parser2/test_files/error_recovery/items/struct_.snap index cddf79090..255768049 100644 --- a/crates/parser2/test_files/error_recovery/items/struct_.snap +++ b/crates/parser2/test_files/error_recovery/items/struct_.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/struct_.fe --- Root@0..160 ItemList@0..160 - Item@0..76 + Item@0..74 Struct@0..74 ItemModifier@0..3 PubKw@0..3 "pub" @@ -68,7 +68,7 @@ Root@0..160 Ident@69..72 "foo" Newline@72..73 "\n" RBrace@73..74 "}" - Newline@74..76 "\n\n" + Newline@74..76 "\n\n" Item@76..160 Struct@76..160 ItemModifier@76..79 diff --git a/crates/parser2/test_files/error_recovery/items/trait_.snap b/crates/parser2/test_files/error_recovery/items/trait_.snap index 4768468b2..99e95864e 100644 --- a/crates/parser2/test_files/error_recovery/items/trait_.snap +++ b/crates/parser2/test_files/error_recovery/items/trait_.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/trait_.fe --- Root@0..133 ItemList@0..133 - Item@0..20 + Item@0..18 Trait@0..18 TraitKw@0..5 "trait" WhiteSpace@5..6 " " @@ -23,8 +23,8 @@ Root@0..133 TraitItemList@16..18 LBrace@16..17 "{" RBrace@17..18 "}" - Newline@18..20 "\n\n" - Item@20..37 + Newline@18..20 "\n\n" + Item@20..35 Trait@20..35 TraitKw@20..25 "trait" WhiteSpace@25..26 " " @@ -38,7 +38,7 @@ Root@0..133 TraitItemList@33..35 LBrace@33..34 "{" RBrace@34..35 "}" - Newline@35..37 "\n\n" + Newline@35..37 "\n\n" Item@37..51 Trait@37..51 TraitKw@37..42 "trait" @@ -52,7 +52,7 @@ Root@0..133 WhiteSpace@49..50 " " Gt@50..51 ">" Newline@51..53 "\n\n" - Item@53..87 + Item@53..85 Trait@53..85 TraitKw@53..58 "trait" WhiteSpace@58..59 " " @@ -88,7 +88,7 @@ Root@0..133 TraitItemList@83..85 LBrace@83..84 "{" RBrace@84..85 "}" - Newline@85..87 "\n\n" + Newline@85..87 "\n\n" Item@87..133 Trait@87..133 TraitKw@87..92 "trait" diff --git a/crates/parser2/test_files/error_recovery/items/type_.snap b/crates/parser2/test_files/error_recovery/items/type_.snap index d5292f1c3..968b01aa9 100644 --- a/crates/parser2/test_files/error_recovery/items/type_.snap +++ b/crates/parser2/test_files/error_recovery/items/type_.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/error_recovery/items/type_.fe --- Root@0..72 - ItemList@0..72 - Item@0..31 + ItemList@0..70 + Item@0..29 TypeAlias@0..29 TypeKw@0..4 "type" WhiteSpace@4..5 " " @@ -37,8 +37,8 @@ Root@0..72 PathSegment@27..28 Ident@27..28 "E" Gt@28..29 ">" - Newline@29..31 "\n\n" - Item@31..72 + Newline@29..31 "\n\n" + Item@31..70 TypeAlias@31..70 TypeKw@31..35 "type" WhiteSpace@35..36 " " @@ -86,5 +86,5 @@ Root@0..72 PathSegment@68..69 Ident@68..69 "U" Gt@69..70 ">" - Newline@70..72 "\n\n" + Newline@70..72 "\n\n" diff --git a/crates/parser2/test_files/error_recovery/items/use_.snap b/crates/parser2/test_files/error_recovery/items/use_.snap index 120cd71b4..5d052e46a 100644 --- a/crates/parser2/test_files/error_recovery/items/use_.snap +++ b/crates/parser2/test_files/error_recovery/items/use_.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/error_recovery/items/use_.fe --- Root@0..63 ItemList@0..63 - Item@0..19 + Item@0..18 Use@0..18 UseKw@0..3 "use" WhiteSpace@3..4 " " @@ -22,8 +22,8 @@ Root@0..63 Colon2@15..17 "::" UsePathSegment@17..18 Ident@17..18 "A" - Newline@18..19 "\n" - Item@19..43 + Newline@18..19 "\n" + Item@19..42 Use@19..42 UseKw@19..22 "use" WhiteSpace@22..23 " " @@ -51,7 +51,7 @@ Root@0..63 UsePathSegment@40..41 Ident@40..41 "B" RBrace@41..42 "}" - Newline@42..43 "\n" + Newline@42..43 "\n" Item@43..63 Use@43..63 UseKw@43..46 "use" diff --git a/crates/parser2/test_files/error_recovery/stmts/for_.snap b/crates/parser2/test_files/error_recovery/stmts/for_.snap index bd08005e3..d74f0a69b 100644 --- a/crates/parser2/test_files/error_recovery/stmts/for_.snap +++ b/crates/parser2/test_files/error_recovery/stmts/for_.snap @@ -16,8 +16,10 @@ Root@0..71 PathSegment@6..7 Ident@6..7 "i" WhiteSpace@7..8 " " - Error@8..11 - Ident@8..11 "arr" + PathExpr@8..11 + Path@8..11 + PathSegment@8..11 + Ident@8..11 "arr" WhiteSpace@11..12 " " BlockExpr@12..15 LBrace@12..13 "{" diff --git a/crates/parser2/test_files/syntax_node/exprs/block.snap b/crates/parser2/test_files/syntax_node/exprs/block.snap index b19de81ef..4c6ab0b26 100644 --- a/crates/parser2/test_files/syntax_node/exprs/block.snap +++ b/crates/parser2/test_files/syntax_node/exprs/block.snap @@ -8,7 +8,7 @@ Root@0..75 LBrace@0..1 "{" Newline@1..2 "\n" WhiteSpace@2..6 " " - Item@6..21 + Item@6..20 Use@6..20 UseKw@6..9 "use" WhiteSpace@9..10 " " @@ -19,9 +19,9 @@ Root@0..75 Colon2@15..17 "::" UsePathSegment@17..20 Ident@17..20 "Foo" - Newline@20..21 "\n" + Newline@20..21 "\n" WhiteSpace@21..25 " " - Item@25..39 + Item@25..38 Struct@25..38 StructKw@25..31 "struct" WhiteSpace@31..32 " " @@ -30,9 +30,9 @@ Root@0..75 RecordFieldDefList@36..38 LBrace@36..37 "{" RBrace@37..38 "}" - Newline@38..39 "\n" + Newline@38..39 "\n" WhiteSpace@39..43 " " - Item@43..55 + Item@43..54 Func@43..54 FnKw@43..45 "fn" WhiteSpace@45..46 " " @@ -44,7 +44,7 @@ Root@0..75 BlockExpr@52..54 LBrace@52..53 "{" RBrace@53..54 "}" - Newline@54..55 "\n" + Newline@54..55 "\n" WhiteSpace@55..59 " " Newline@59..60 "\n" WhiteSpace@60..64 " " diff --git a/crates/parser2/test_files/syntax_node/items/const.snap b/crates/parser2/test_files/syntax_node/items/const.snap index 8808db0b7..6b23631b3 100644 --- a/crates/parser2/test_files/syntax_node/items/const.snap +++ b/crates/parser2/test_files/syntax_node/items/const.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/syntax_node/items/const.fe --- Root@0..160 - ItemList@0..160 - Item@0..24 + ItemList@0..159 + Item@0..22 Const@0..22 ItemModifier@0..3 PubKw@0..3 "pub" @@ -25,8 +25,8 @@ Root@0..160 LitExpr@21..22 Lit@21..22 Int@21..22 "1" - Newline@22..24 "\n\n" - Item@24..160 + Newline@22..24 "\n\n" + Item@24..159 Const@24..159 ConstKw@24..29 "const" WhiteSpace@29..30 " " @@ -139,5 +139,5 @@ Root@0..160 RBrace@156..157 "}" Newline@157..158 "\n" RBrace@158..159 "}" - Newline@159..160 "\n" + Newline@159..160 "\n" diff --git a/crates/parser2/test_files/syntax_node/items/contract.snap b/crates/parser2/test_files/syntax_node/items/contract.snap index 2119b58bd..b66008047 100644 --- a/crates/parser2/test_files/syntax_node/items/contract.snap +++ b/crates/parser2/test_files/syntax_node/items/contract.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/contract.fe --- Root@0..90 ItemList@0..90 - Item@0..19 + Item@0..17 Contract@0..17 ContractKw@0..8 "contract" WhiteSpace@8..9 " " @@ -14,7 +14,7 @@ Root@0..90 RecordFieldDefList@15..17 LBrace@15..16 "{" RBrace@16..17 "}" - Newline@17..19 "\n\n" + Newline@17..19 "\n\n" Item@19..90 Contract@19..90 ItemModifier@19..22 diff --git a/crates/parser2/test_files/syntax_node/items/enums.snap b/crates/parser2/test_files/syntax_node/items/enums.snap index 734018e9f..dea236660 100644 --- a/crates/parser2/test_files/syntax_node/items/enums.snap +++ b/crates/parser2/test_files/syntax_node/items/enums.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/syntax_node/items/enums.fe --- Root@0..493 - ItemList@0..493 - Item@0..15 + ItemList@0..492 + Item@0..13 Enum@0..13 EnumKw@0..4 "enum" WhiteSpace@4..5 " " @@ -14,8 +14,8 @@ Root@0..493 VariantDefList@11..13 LBrace@11..12 "{" RBrace@12..13 "}" - Newline@13..15 "\n\n" - Item@15..59 + Newline@13..15 "\n\n" + Item@15..57 Enum@15..57 EnumKw@15..19 "enum" WhiteSpace@19..20 " " @@ -47,8 +47,8 @@ Root@0..493 RParen@54..55 ")" Newline@55..56 "\n" RBrace@56..57 "}" - Newline@57..59 "\n\n" - Item@59..142 + Newline@57..59 "\n\n" + Item@59..140 Enum@59..140 EnumKw@59..63 "enum" WhiteSpace@63..64 " " @@ -105,8 +105,8 @@ Root@0..493 RBrace@137..138 "}" Newline@138..139 "\n" RBrace@139..140 "}" - Newline@140..142 "\n\n" - Item@142..204 + Newline@140..142 "\n\n" + Item@142..202 Enum@142..202 EnumKw@142..146 "enum" WhiteSpace@146..147 " " @@ -156,8 +156,8 @@ Root@0..493 Comma@199..200 "," Newline@200..201 "\n" RBrace@201..202 "}" - Newline@202..204 "\n\n" - Item@204..308 + Newline@202..204 "\n\n" + Item@204..306 Enum@204..306 EnumKw@204..208 "enum" WhiteSpace@208..209 " " @@ -261,8 +261,8 @@ Root@0..493 Comma@303..304 "," Newline@304..305 "\n" RBrace@305..306 "}" - Newline@306..308 "\n\n" - Item@308..436 + Newline@306..308 "\n\n" + Item@308..434 Enum@308..434 EnumKw@308..312 "enum" WhiteSpace@312..313 " " @@ -416,8 +416,8 @@ Root@0..493 RParen@431..432 ")" Newline@432..433 "\n" RBrace@433..434 "}" - Newline@434..436 "\n\n" - Item@436..493 + Newline@434..436 "\n\n" + Item@436..492 Enum@436..492 EnumKw@436..440 "enum" WhiteSpace@440..441 " " @@ -479,5 +479,5 @@ Root@0..493 RParen@489..490 ")" WhiteSpace@490..491 " " RBrace@491..492 "}" - Newline@492..493 "\n" + Newline@492..493 "\n" diff --git a/crates/parser2/test_files/syntax_node/items/extern.snap b/crates/parser2/test_files/syntax_node/items/extern.snap index 05a72a60d..5a89154c0 100644 --- a/crates/parser2/test_files/syntax_node/items/extern.snap +++ b/crates/parser2/test_files/syntax_node/items/extern.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/extern.fe --- Root@0..146 ItemList@0..146 - Item@0..13 + Item@0..11 Extern@0..11 ExternKw@0..6 "extern" WhiteSpace@6..7 " " @@ -13,7 +13,7 @@ Root@0..146 LBrace@7..8 "{" Newline@8..10 "\n\n" RBrace@10..11 "}" - Newline@11..13 "\n\n" + Newline@11..13 "\n\n" Item@13..146 Extern@13..146 ExternKw@13..19 "extern" diff --git a/crates/parser2/test_files/syntax_node/items/func.snap b/crates/parser2/test_files/syntax_node/items/func.snap index c1c5235f6..52e9c4036 100644 --- a/crates/parser2/test_files/syntax_node/items/func.snap +++ b/crates/parser2/test_files/syntax_node/items/func.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/func.fe --- Root@0..351 ItemList@0..351 - Item@0..32 + Item@0..30 Func@0..30 ItemModifier@0..3 PubKw@0..3 "pub" @@ -36,8 +36,8 @@ Root@0..351 Int@27..28 "1" Newline@28..29 "\n" RBrace@29..30 "}" - Newline@30..32 "\n\n" - Item@32..82 + Newline@30..32 "\n\n" + Item@32..80 Func@32..80 FnKw@32..34 "fn" WhiteSpace@34..35 " " @@ -83,8 +83,8 @@ Root@0..351 Int@77..78 "1" Newline@78..79 "\n" RBrace@79..80 "}" - Newline@80..82 "\n\n" - Item@82..180 + Newline@80..82 "\n\n" + Item@82..178 Func@82..178 FnKw@82..84 "fn" WhiteSpace@84..85 " " @@ -158,8 +158,8 @@ Root@0..351 Int@175..176 "1" Newline@176..177 "\n" RBrace@177..178 "}" - Newline@178..180 "\n\n" - Item@180..298 + Newline@178..180 "\n\n" + Item@180..296 Func@180..296 FnKw@180..182 "fn" WhiteSpace@182..183 " " @@ -279,7 +279,7 @@ Root@0..351 Ident@293..294 "t" Newline@294..295 "\n" RBrace@295..296 "}" - Newline@296..298 "\n\n" + Newline@296..298 "\n\n" Item@298..351 Func@298..351 FnKw@298..300 "fn" diff --git a/crates/parser2/test_files/syntax_node/items/impl.snap b/crates/parser2/test_files/syntax_node/items/impl.snap index c984174c5..da14d9275 100644 --- a/crates/parser2/test_files/syntax_node/items/impl.snap +++ b/crates/parser2/test_files/syntax_node/items/impl.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/impl.fe --- Root@0..272 ItemList@0..272 - Item@0..139 + Item@0..137 Impl@0..137 ImplKw@0..4 "impl" GenericParamList@4..12 @@ -112,7 +112,7 @@ Root@0..272 RBrace@134..135 "}" Newline@135..136 "\n" RBrace@136..137 "}" - Newline@137..139 "\n\n" + Newline@137..139 "\n\n" Item@139..272 Impl@139..272 ImplKw@139..143 "impl" diff --git a/crates/parser2/test_files/syntax_node/items/impl_trait.snap b/crates/parser2/test_files/syntax_node/items/impl_trait.snap index aaa6cb9c8..cba9fbebb 100644 --- a/crates/parser2/test_files/syntax_node/items/impl_trait.snap +++ b/crates/parser2/test_files/syntax_node/items/impl_trait.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/impl_trait.fe --- Root@0..334 ItemList@0..334 - Item@0..69 + Item@0..67 ImplTrait@0..67 ImplKw@0..4 "impl" GenericParamList@4..7 @@ -69,8 +69,8 @@ Root@0..334 RBrace@64..65 "}" Newline@65..66 "\n" RBrace@66..67 "}" - Newline@67..69 "\n\n" - Item@69..207 + Newline@67..69 "\n\n" + Item@69..205 ImplTrait@69..205 ImplKw@69..73 "impl" GenericParamList@73..79 @@ -223,7 +223,7 @@ Root@0..334 RBrace@202..203 "}" Newline@203..204 "\n" RBrace@204..205 "}" - Newline@205..207 "\n\n" + Newline@205..207 "\n\n" Item@207..334 ImplTrait@207..334 ImplKw@207..211 "impl" diff --git a/crates/parser2/test_files/syntax_node/items/mod.snap b/crates/parser2/test_files/syntax_node/items/mod.snap index d5cd3c1e7..60b6e63e9 100644 --- a/crates/parser2/test_files/syntax_node/items/mod.snap +++ b/crates/parser2/test_files/syntax_node/items/mod.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/mod.fe --- Root@0..146 ItemList@0..146 - Item@0..109 + Item@0..107 Mod@0..107 ItemModifier@0..3 PubKw@0..3 "pub" @@ -18,7 +18,7 @@ Root@0..146 LBrace@12..13 "{" Newline@13..14 "\n" WhiteSpace@14..18 " " - Item@18..79 + Item@18..78 Func@18..78 FnKw@18..20 "fn" WhiteSpace@20..21 " " @@ -65,11 +65,11 @@ Root@0..146 Newline@72..73 "\n" WhiteSpace@73..77 " " RBrace@77..78 "}" - Newline@78..79 "\n" + Newline@78..79 "\n" WhiteSpace@79..83 " " Newline@83..84 "\n" WhiteSpace@84..88 " " - Item@88..106 + Item@88..105 Struct@88..105 ItemModifier@88..91 PubKw@88..91 "pub" @@ -81,9 +81,9 @@ Root@0..146 RecordFieldDefList@103..105 LBrace@103..104 "{" RBrace@104..105 "}" - Newline@105..106 "\n" + Newline@105..106 "\n" RBrace@106..107 "}" - Newline@107..109 "\n\n" + Newline@107..109 "\n\n" Item@109..146 Mod@109..146 ItemModifier@109..112 @@ -97,7 +97,7 @@ Root@0..146 LBrace@121..122 "{" Newline@122..123 "\n" WhiteSpace@123..127 " " - Item@127..145 + Item@127..144 Struct@127..144 ItemModifier@127..130 PubKw@127..130 "pub" @@ -109,6 +109,6 @@ Root@0..146 RecordFieldDefList@142..144 LBrace@142..143 "{" RBrace@143..144 "}" - Newline@144..145 "\n" + Newline@144..145 "\n" RBrace@145..146 "}" diff --git a/crates/parser2/test_files/syntax_node/items/trait.snap b/crates/parser2/test_files/syntax_node/items/trait.snap index 60cb70e80..4d29724f5 100644 --- a/crates/parser2/test_files/syntax_node/items/trait.snap +++ b/crates/parser2/test_files/syntax_node/items/trait.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/trait.fe --- Root@0..652 ItemList@0..652 - Item@0..17 + Item@0..15 Trait@0..15 TraitKw@0..5 "trait" WhiteSpace@5..6 " " @@ -14,8 +14,8 @@ Root@0..652 TraitItemList@13..15 LBrace@13..14 "{" RBrace@14..15 "}" - Newline@15..17 "\n\n" - Item@17..184 + Newline@15..17 "\n\n" + Item@17..182 Trait@17..182 ItemModifier@17..20 PubKw@17..20 "pub" @@ -175,8 +175,8 @@ Root@0..652 RBrace@179..180 "}" Newline@180..181 "\n" RBrace@181..182 "}" - Newline@182..184 "\n\n" - Item@184..274 + Newline@182..184 "\n\n" + Item@184..271 Trait@184..271 ItemModifier@184..187 PubKw@184..187 "pub" @@ -248,8 +248,8 @@ Root@0..652 Ident@266..269 "Sub" Newline@269..270 "\n" RBrace@270..271 "}" - Newline@271..274 "\n\n\n" - Item@274..357 + Newline@271..274 "\n\n\n" + Item@274..355 Trait@274..355 ItemModifier@274..277 PubKw@274..277 "pub" @@ -308,8 +308,8 @@ Root@0..652 RParen@352..353 ")" Newline@353..354 "\n" RBrace@354..355 "}" - Newline@355..357 "\n\n" - Item@357..595 + Newline@355..357 "\n\n" + Item@357..592 Impl@357..592 ImplKw@357..361 "impl" GenericParamList@361..364 @@ -483,7 +483,7 @@ Root@0..652 RBrace@589..590 "}" Newline@590..591 "\n" RBrace@591..592 "}" - Newline@592..595 "\n\n\n" + Newline@592..595 "\n\n\n" Item@595..652 Trait@595..652 ItemModifier@595..598 diff --git a/crates/parser2/test_files/syntax_node/items/type.snap b/crates/parser2/test_files/syntax_node/items/type.snap index 6148c44b0..d3a347df8 100644 --- a/crates/parser2/test_files/syntax_node/items/type.snap +++ b/crates/parser2/test_files/syntax_node/items/type.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/items/type.fe --- Root@0..54 ItemList@0..54 - Item@0..21 + Item@0..18 TypeAlias@0..18 ItemModifier@0..3 PubKw@0..3 "pub" @@ -20,8 +20,8 @@ Root@0..54 Path@15..18 PathSegment@15..18 Ident@15..18 "i32" - WhiteSpace@18..19 " " - Newline@19..21 "\n\n" + WhiteSpace@18..19 " " + Newline@19..21 "\n\n" Item@21..54 TypeAlias@21..54 TypeKw@21..25 "type" diff --git a/crates/parser2/test_files/syntax_node/items/use.snap b/crates/parser2/test_files/syntax_node/items/use.snap index c7ceedab2..d425d218c 100644 --- a/crates/parser2/test_files/syntax_node/items/use.snap +++ b/crates/parser2/test_files/syntax_node/items/use.snap @@ -4,8 +4,8 @@ expression: node input_file: crates/parser2/test_files/syntax_node/items/use.fe --- Root@0..308 - ItemList@0..308 - Item@0..13 + ItemList@0..307 + Item@0..12 Use@0..12 UseKw@0..3 "use" WhiteSpace@3..4 " " @@ -16,8 +16,8 @@ Root@0..308 Colon2@7..9 "::" UsePathSegment@9..12 Ident@9..12 "Bar" - Newline@12..13 "\n" - Item@13..30 + Newline@12..13 "\n" + Item@13..29 Use@13..29 ItemModifier@13..16 PubKw@13..16 "pub" @@ -31,8 +31,8 @@ Root@0..308 Colon2@24..26 "::" UsePathSegment@26..29 Ident@26..29 "Bar" - Newline@29..30 "\n" - Item@30..41 + Newline@29..30 "\n" + Item@30..40 Use@30..40 UseKw@30..33 "use" WhiteSpace@33..34 " " @@ -43,8 +43,8 @@ Root@0..308 Colon2@37..39 "::" UsePathSegment@39..40 Star@39..40 "*" - Newline@40..41 "\n" - Item@41..62 + Newline@40..41 "\n" + Item@41..61 Use@41..61 UseKw@41..44 "use" WhiteSpace@44..45 " " @@ -60,8 +60,8 @@ Root@0..308 AsKw@54..56 "as" WhiteSpace@56..57 " " Ident@57..61 "Bar1" - Newline@61..62 "\n" - Item@62..83 + Newline@61..62 "\n" + Item@62..81 Use@62..81 UseKw@62..65 "use" WhiteSpace@65..66 " " @@ -77,8 +77,8 @@ Root@0..308 AsKw@77..79 "as" WhiteSpace@79..80 " " Underscore@80..81 "_" - Newline@81..83 "\n\n" - Item@83..103 + Newline@81..83 "\n\n" + Item@83..102 Use@83..102 UseKw@83..86 "use" WhiteSpace@86..87 " " @@ -100,8 +100,8 @@ Root@0..308 UsePathSegment@98..101 Ident@98..101 "Bar" RBrace@101..102 "}" - Newline@102..103 "\n" - Item@103..124 + Newline@102..103 "\n" + Item@103..123 Use@103..123 UseKw@103..106 "use" WhiteSpace@106..107 " " @@ -123,8 +123,8 @@ Root@0..308 UsePathSegment@119..122 Ident@119..122 "Bar" RBrace@122..123 "}" - Newline@123..124 "\n" - Item@124..153 + Newline@123..124 "\n" + Item@124..152 Use@124..152 UseKw@124..127 "use" WhiteSpace@127..128 " " @@ -151,8 +151,8 @@ Root@0..308 WhiteSpace@146..147 " " Ident@147..151 "Bar1" RBrace@151..152 "}" - Newline@152..153 "\n" - Item@153..204 + Newline@152..153 "\n" + Item@153..202 Use@153..202 UseKw@153..156 "use" WhiteSpace@156..157 " " @@ -204,8 +204,8 @@ Root@0..308 UsePathSegment@200..201 Star@200..201 "*" RBrace@201..202 "}" - Newline@202..204 "\n\n" - Item@204..273 + Newline@202..204 "\n\n" + Item@204..272 Use@204..272 UseKw@204..207 "use" WhiteSpace@207..208 " " @@ -262,8 +262,8 @@ Root@0..308 UsePathSegment@270..271 Ident@270..271 "T" RBrace@271..272 "}" - Newline@272..273 "\n" - Item@273..280 + Newline@272..273 "\n" + Item@273..278 Use@273..278 UseKw@273..276 "use" WhiteSpace@276..277 " " @@ -271,8 +271,8 @@ Root@0..308 UsePath@277..278 UsePathSegment@277..278 Star@277..278 "*" - Newline@278..280 "\n\n" - Item@280..293 + Newline@278..280 "\n\n" + Item@280..292 Use@280..292 UseKw@280..283 "use" WhiteSpace@283..284 " " @@ -283,8 +283,8 @@ Root@0..308 Colon2@289..291 "::" UsePathSegment@291..292 Star@291..292 "*" - Newline@292..293 "\n" - Item@293..308 + Newline@292..293 "\n" + Item@293..307 Use@293..307 UseKw@293..296 "use" WhiteSpace@296..297 " " @@ -295,5 +295,5 @@ Root@0..308 Colon2@302..304 "::" UsePathSegment@304..307 Ident@304..307 "Foo" - Newline@307..308 "\n" + Newline@307..308 "\n" diff --git a/crates/parser2/test_files/syntax_node/structs/generics.snap b/crates/parser2/test_files/syntax_node/structs/generics.snap index b714a4ad3..6debda1ee 100644 --- a/crates/parser2/test_files/syntax_node/structs/generics.snap +++ b/crates/parser2/test_files/syntax_node/structs/generics.snap @@ -5,7 +5,7 @@ input_file: crates/parser2/test_files/syntax_node/structs/generics.fe --- Root@0..563 ItemList@0..563 - Item@0..78 + Item@0..76 Struct@0..76 ItemModifier@0..3 PubKw@0..3 "pub" @@ -64,8 +64,8 @@ Root@0..563 Comma@73..74 "," Newline@74..75 "\n" RBrace@75..76 "}" - Newline@76..78 "\n\n" - Item@78..192 + Newline@76..78 "\n\n" + Item@78..190 Struct@78..190 ItemModifier@78..81 PubKw@78..81 "pub" @@ -153,8 +153,8 @@ Root@0..563 Comma@187..188 "," Newline@188..189 "\n" RBrace@189..190 "}" - Newline@190..192 "\n\n" - Item@192..416 + Newline@190..192 "\n\n" + Item@192..414 Struct@192..414 ItemModifier@192..195 PubKw@192..195 "pub" @@ -342,7 +342,7 @@ Root@0..563 Comma@411..412 "," Newline@412..413 "\n" RBrace@413..414 "}" - Newline@414..416 "\n\n" + Newline@414..416 "\n\n" Item@416..563 Struct@416..563 ItemModifier@416..419 diff --git a/crates/uitest/fixtures/parser/array.snap b/crates/uitest/fixtures/parser/array.snap index d7e1b5530..c0635ba26 100644 --- a/crates/uitest/fixtures/parser/array.snap +++ b/crates/uitest/fixtures/parser/array.snap @@ -3,10 +3,10 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/array.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing array definition ┌─ array.fe:2:7 │ 2 │ [1, 2 a, 3] - │ ^ unexpected syntax + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/block.snap b/crates/uitest/fixtures/parser/block.snap index f9c92cf9d..e18fd8610 100644 --- a/crates/uitest/fixtures/parser/block.snap +++ b/crates/uitest/fixtures/parser/block.snap @@ -3,16 +3,10 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/block.fe --- -error[1-0001]: expected newline after statement - ┌─ block.fe:3:15 - │ -3 │ let x: i32 u32 = 10 - │ ^ expected newline after statement - -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing block ┌─ block.fe:3:16 │ 3 │ let x: i32 u32 = 10 - │ ^^^^^^^^ unexpected syntax + │ ^^^^^^^^ unexpected diff --git a/crates/uitest/fixtures/parser/call.snap b/crates/uitest/fixtures/parser/call.snap index 349b3acb4..78ba7e21a 100644 --- a/crates/uitest/fixtures/parser/call.snap +++ b/crates/uitest/fixtures/parser/call.snap @@ -3,22 +3,22 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/call.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function call arguments ┌─ call.fe:2:10 │ 2 │ foo(x, y a, z ;) - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function call arguments ┌─ call.fe:2:15 │ 2 │ foo(x, y a, z ;) - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing generic type argument list ┌─ call.fe:4:12 │ 4 │ foo(x, y) - │ ^ unexpected syntax + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/const_.snap b/crates/uitest/fixtures/parser/const_.snap index b20e4b9d4..a8a17904e 100644 --- a/crates/uitest/fixtures/parser/const_.snap +++ b/crates/uitest/fixtures/parser/const_.snap @@ -3,28 +3,28 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/const_.fe --- -error[1-0001]: expected type annotation for `const` +error[1-0001]: missing type bound for const definition ┌─ const_.fe:1:8 │ 1 │ const X = 10 - │ ^ expected type annotation for `const` + │ ^ expected `:` -error[1-0001]: expected `=` for const value definition +error[1-0001]: expected `=` ┌─ const_.fe:3:13 │ 3 │ const X: i32 - │ ^ expected `=` for const value definition + │ ^ expected `=` -error[1-0001]: expected path segment - ┌─ const_.fe:5:10 +error[1-0001]: expected type + ┌─ const_.fe:5:9 │ 5 │ const X: ]@ = 1 - │ ^ expected path segment + │ ^ expected type -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing type ┌─ const_.fe:5:10 │ 5 │ const X: ]@ = 1 - │ ^^ unexpected syntax + │ ^^ unexpected diff --git a/crates/uitest/fixtures/parser/enum_.snap b/crates/uitest/fixtures/parser/enum_.snap index a0515384a..a17f1482c 100644 --- a/crates/uitest/fixtures/parser/enum_.snap +++ b/crates/uitest/fixtures/parser/enum_.snap @@ -3,34 +3,34 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/enum_.fe --- -error[1-0001]: expected `)` +error[1-0001]: missing closing `)` for tuple type definition ┌─ enum_.fe:2:13 │ 2 │ X(u32, T - │ ^ expected `)` + │ ^ expected `)` or `,` -error[1-0001]: expected comma after enum variant definition +error[1-0001]: missing closing `}` for `enum` variant list ┌─ enum_.fe:2:13 │ 2 │ X(u32, T - │ ^ expected comma after enum variant definition + │ ^ expected `}` or `,` -error[1-0001]: expected comma after enum variant definition +error[1-0001]: missing closing `}` for `enum` variant list ┌─ enum_.fe:3:6 │ 3 │ A - │ ^ expected comma after enum variant definition + │ ^ expected `}` or `,` -error[1-0001]: expected comma after enum variant definition - ┌─ enum_.fe:4:14 +error[1-0001]: unexpected syntax while parsing `enum` variant list + ┌─ enum_.fe:4:15 │ 4 │ Y(T, u32) A - │ ^ expected comma after enum variant definition + │ ^ unexpected -error[1-0001]: expected comma after enum variant definition +error[1-0001]: missing closing `}` for `enum` variant list ┌─ enum_.fe:4:16 │ 4 │ Y(T, u32) A - │ ^ expected comma after enum variant definition + │ ^ expected `}` or `,` diff --git a/crates/uitest/fixtures/parser/extern_.snap b/crates/uitest/fixtures/parser/extern_.snap index ea4ed0fec..bdd33cecd 100644 --- a/crates/uitest/fixtures/parser/extern_.snap +++ b/crates/uitest/fixtures/parser/extern_.snap @@ -9,10 +9,16 @@ error[1-0001]: only `fn` is allowed in this block 4 │ struct Foo { │ ^^^^^^ only `fn` is allowed in this block -error[1-0001]: unexpected syntax - ┌─ extern_.fe:4:5 +error[1-0001]: expected name for field + ┌─ extern_.fe:6:8 │ -4 │ struct Foo { - │ ^^^^^^^^^^^^ unexpected syntax +6 │ pub unsafe fn foo() + │ ^ expected identifier + +error[1-0001]: unexpected syntax while parsing function definition + ┌─ extern_.fe:7:1 + │ +7 │ } + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/fn_missing_body.snap b/crates/uitest/fixtures/parser/fn_missing_body.snap index 835c7fdcd..40eea7d4f 100644 --- a/crates/uitest/fixtures/parser/fn_missing_body.snap +++ b/crates/uitest/fixtures/parser/fn_missing_body.snap @@ -3,22 +3,16 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/fn_missing_body.fe --- -error[1-0001]: function body is required +error[1-0001]: expected `{` or `where` ┌─ fn_missing_body.fe:1:28 │ 1 │ fn foo(x: u8, y: u64) -> u8 - │ ^ function body is required + │ ^ expected `{` or `where` -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function definition ┌─ fn_missing_body.fe:3:13 │ 3 │ fn bar() asdf - │ ^^^^ unexpected syntax - -error[1-0001]: function body is required - ┌─ fn_missing_body.fe:3:17 - │ -3 │ fn bar() asdf - │ ^ function body is required + │ ^^^^ unexpected diff --git a/crates/uitest/fixtures/parser/fn_missing_parameters.snap b/crates/uitest/fixtures/parser/fn_missing_parameters.snap index 581a2f8ff..5240af858 100644 --- a/crates/uitest/fixtures/parser/fn_missing_parameters.snap +++ b/crates/uitest/fixtures/parser/fn_missing_parameters.snap @@ -3,34 +3,28 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/fn_missing_parameters.fe --- -error[1-0001]: expected `(` for the function arguments +error[1-0001]: expected function parameter list ┌─ fn_missing_parameters.fe:1:7 │ 1 │ fn foo -> u8 {} - │ ^ expected `(` for the function arguments + │ ^ expected `(` -error[1-0001]: expected `(` for the function arguments +error[1-0001]: expected function parameter list ┌─ fn_missing_parameters.fe:3:7 │ 3 │ fn bar { - │ ^ expected `(` for the function arguments + │ ^ expected `(` -error[1-0001]: expected `(` for the function arguments +error[1-0001]: expected function parameter list ┌─ fn_missing_parameters.fe:6:7 │ 6 │ fn baz -> u8 {} - │ ^ expected `(` for the function arguments + │ ^ expected `(` -error[1-0001]: expected `(` for the function arguments +error[1-0001]: expected function parameter list ┌─ fn_missing_parameters.fe:8:8 │ 8 │ fn f where T: U {} - │ ^ expected `(` for the function arguments - -error[1-0001]: expected newline after type bounds - ┌─ fn_missing_parameters.fe:8:19 - │ -8 │ fn f where T: U {} - │ ^ expected newline after type bounds + │ ^ expected `(` diff --git a/crates/uitest/fixtures/parser/fn_modifiers.snap b/crates/uitest/fixtures/parser/fn_modifiers.snap index 90584fadc..8e560a1bf 100644 --- a/crates/uitest/fixtures/parser/fn_modifiers.snap +++ b/crates/uitest/fixtures/parser/fn_modifiers.snap @@ -3,76 +3,76 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/fn_modifiers.fe --- -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `pub` modifier ┌─ fn_modifiers.fe:1:5 │ 1 │ pub pub struct Foo {} - │ ^^^ duplicate modifier + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `pub` modifier ┌─ fn_modifiers.fe:3:9 │ 3 │ pub pub unsafe unsafe fn f() {} - │ ^^^ duplicate modifier + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `unsafe` modifier ┌─ fn_modifiers.fe:3:20 │ 3 │ pub pub unsafe unsafe fn f() {} - │ ^^^^^^ duplicate modifier + │ ^^^^^^ unexpected error[1-0001]: `pub` modifier must come before `unsafe` ┌─ fn_modifiers.fe:4:12 │ 4 │ unsafe pub fn g() {} - │ ^^^ `pub` modifier must come before `unsafe` + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `unsafe` modifier ┌─ fn_modifiers.fe:5:12 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^^^^ duplicate modifier + │ ^^^^^^ unexpected error[1-0001]: `pub` modifier must come before `unsafe` ┌─ fn_modifiers.fe:5:19 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^ `pub` modifier must come before `unsafe` + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `unsafe` modifier ┌─ fn_modifiers.fe:5:23 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^^^^ duplicate modifier + │ ^^^^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `pub` modifier ┌─ fn_modifiers.fe:5:30 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^ duplicate modifier + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `pub` modifier ┌─ fn_modifiers.fe:5:34 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^ duplicate modifier + │ ^^^ unexpected -error[1-0001]: duplicate modifier +error[1-0001]: duplicate `unsafe` modifier ┌─ fn_modifiers.fe:5:38 │ 5 │ unsafe unsafe pub unsafe pub pub unsafe fn h() {} - │ ^^^^^^ duplicate modifier + │ ^^^^^^ unexpected -error[1-0001]: modifier is not allowed in this block +error[1-0001]: `pub` modifier is not allowed in this block ┌─ fn_modifiers.fe:13:5 │ 13 │ pub unsafe fn f(self) {} - │ ^^^ modifier is not allowed in this block + │ ^^^ unexpected -error[1-0001]: modifier is not allowed in this block +error[1-0001]: `unsafe` modifier is not allowed in this block ┌─ fn_modifiers.fe:13:9 │ 13 │ pub unsafe fn f(self) {} - │ ^^^^^^ modifier is not allowed in this block + │ ^^^^^^ unexpected diff --git a/crates/uitest/fixtures/parser/for_.snap b/crates/uitest/fixtures/parser/for_.snap index 7ab22c537..38a718c03 100644 --- a/crates/uitest/fixtures/parser/for_.snap +++ b/crates/uitest/fixtures/parser/for_.snap @@ -3,46 +3,46 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/for_.fe --- -error[1-0001]: expected `in` keyword +error[1-0001]: expected `in` ┌─ for_.fe:2:6 │ 2 │ for i arr { } - │ ^ expected `in` keyword + │ ^ expected `in` -error[1-0001]: expected path segment - ┌─ for_.fe:4:5 +error[1-0001]: expected pattern + ┌─ for_.fe:4:4 │ 4 │ for in arr { } - │ ^ expected path segment + │ ^ expected pattern -error[1-0001]: expected path segment - ┌─ for_.fe:6:5 +error[1-0001]: expected pattern + ┌─ for_.fe:6:4 │ 6 │ for @ in arr {} - │ ^ expected path segment + │ ^ expected pattern -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing pattern ┌─ for_.fe:6:5 │ 6 │ for @ in arr {} - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: expected path segment - ┌─ for_.fe:8:5 +error[1-0001]: expected pattern + ┌─ for_.fe:8:4 │ 8 │ for @ in arr x y {} - │ ^ expected path segment + │ ^ expected pattern -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing pattern ┌─ for_.fe:8:5 │ 8 │ for @ in arr x y {} - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `for` statement ┌─ for_.fe:8:14 │ 8 │ for @ in arr x y {} - │ ^^^ unexpected syntax + │ ^^^ unexpected diff --git a/crates/uitest/fixtures/parser/func.fe b/crates/uitest/fixtures/parser/func.fe index 481ba1e97..b2848720d 100644 --- a/crates/uitest/fixtures/parser/func.fe +++ b/crates/uitest/fixtures/parser/func.fe @@ -1,10 +1,13 @@ -fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 +fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 { } fn foo<<(x: i32) - where T: Trait2 + where T: Trait2 { } + +fn bar() + where T: 75 {} \ No newline at end of file diff --git a/crates/uitest/fixtures/parser/func.snap b/crates/uitest/fixtures/parser/func.snap index 1d09f337b..0d7cdc30b 100644 --- a/crates/uitest/fixtures/parser/func.snap +++ b/crates/uitest/fixtures/parser/func.snap @@ -3,28 +3,52 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/func.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function definition ┌─ func.fe:1:17 │ -1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 - │ ^ unexpected syntax +1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 + │ ^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function parameter ┌─ func.fe:1:29 │ -1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 - │ ^^^ unexpected syntax +1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 + │ ^^^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function definition ┌─ func.fe:1:54 │ -1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 - │ ^^^ unexpected syntax +1 │ fn foo>(x: i32, _ mut y: u32, z: u32) -> T, u where T: Trait2 + │ ^^^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing generic parameter list ┌─ func.fe:6:8 │ 6 │ fn foo<<(x: i32) - │ ^^ unexpected syntax + │ ^^ unexpected + +error[1-0001]: expected trait name + ┌─ func.fe:12:10 + │ +12 │ fn bar() + │ ^ expected trait name + +error[1-0001]: unexpected syntax while parsing trait name + ┌─ func.fe:12:11 + │ +12 │ fn bar() + │ ^ unexpected + +error[1-0001]: expected trait name + ┌─ func.fe:13:13 + │ +13 │ where T: 75 {} + │ ^ expected trait name + +error[1-0001]: unexpected syntax while parsing trait name + ┌─ func.fe:13:14 + │ +13 │ where T: 75 {} + │ ^^ unexpected diff --git a/crates/uitest/fixtures/parser/if_.snap b/crates/uitest/fixtures/parser/if_.snap index 2d56b32f3..0faed6fa9 100644 --- a/crates/uitest/fixtures/parser/if_.snap +++ b/crates/uitest/fixtures/parser/if_.snap @@ -3,59 +3,23 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/if_.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `if` expression ┌─ if_.fe:3:6 │ 3 │ if x y { - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: expected `{` or `if` after `else` - ┌─ if_.fe:8:7 - │ -8 │ } else x {} - │ ^ expected `{` or `if` after `else` - -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `if` expression ┌─ if_.fe:8:8 │ 8 │ } else x {} - │ ^ unexpected syntax - -error[1-0001]: expected newline after statement - ┌─ if_.fe:8:9 - │ -8 │ } else x {} - │ ^ expected newline after statement - -error[1-0001]: unexpected syntax - ┌─ if_.fe:8:10 - │ -8 │ } else x {} - │ ^^ unexpected syntax - -error[1-0001]: expected `{` or `if` after `else` - ┌─ if_.fe:10:14 - │ -10 │ if x { } else x if x { } else { } - │ ^ expected `{` or `if` after `else` + │ ^ unexpected -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `if` expression ┌─ if_.fe:10:15 │ 10 │ if x { } else x if x { } else { } - │ ^ unexpected syntax - -error[1-0001]: expected newline after statement - ┌─ if_.fe:10:16 - │ -10 │ if x { } else x if x { } else { } - │ ^ expected newline after statement - -error[1-0001]: unexpected syntax - ┌─ if_.fe:10:17 - │ -10 │ if x { } else x if x { } else { } - │ ^^^^^^^^^^^^^^^^^ unexpected syntax + │ ^ unexpected error[1-0001]: expected expression ┌─ if_.fe:14:1 @@ -63,24 +27,4 @@ error[1-0001]: expected expression 14 │ else { │ ^ expected expression -error[1-0001]: unexpected syntax - ┌─ if_.fe:14:1 - │ -14 │ ╭ else { -15 │ │ 1 -16 │ │ } - │ ╰─^ unexpected syntax - -error[1-0001]: expected newline after statement - ┌─ if_.fe:18:2 - │ -18 │ } - │ ^ expected newline after statement - -error[1-0001]: expected `}` - ┌─ if_.fe:18:2 - │ -18 │ } - │ ^ expected `}` - diff --git a/crates/uitest/fixtures/parser/impl_.snap b/crates/uitest/fixtures/parser/impl_.snap index 98820d8cf..47c112976 100644 --- a/crates/uitest/fixtures/parser/impl_.snap +++ b/crates/uitest/fixtures/parser/impl_.snap @@ -3,22 +3,10 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/impl_.fe --- -error[1-0001]: expected path segment - ┌─ impl_.fe:2:5 +error[1-0001]: expected type + ┌─ impl_.fe:1:12 │ -2 │ where T: Integer - │ ^ expected path segment - -error[1-0001]: expected closing `>` - ┌─ impl_.fe:2:5 - │ -2 │ where T: Integer - │ ^ expected closing `>` - -error[1-0001]: expected path segment - ┌─ impl_.fe:5:13 - │ -5 │ impl Foo - │ ^ expected path segment +1 │ impl Foo for Y` +error[1-0001]: missing closing `>` for generic type argument list ┌─ impl_trait.fe:1:23 │ 1 │ impl X for Y` + │ ^ expected `>` or `,` -error[1-0001]: expected newline after type bounds - ┌─ impl_trait.fe:1:34 - │ -1 │ impl X for Y` +error[1-0001]: missing closing `>` for generic type argument list ┌─ impl_trait.fe:3:12 │ 3 │ impl X` + │ ^ expected `>` or `,` -error[1-0001]: expected closing `>` +error[1-0001]: missing closing `>` for generic type argument list ┌─ impl_trait.fe:3:20 │ 3 │ impl X` - -error[1-0001]: expected newline after type bounds - ┌─ impl_trait.fe:3:31 - │ -3 │ impl X` or `,` -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `impl` trait block ┌─ impl_trait.fe:5:8 │ 5 │ impl X @ for Y {} - │ ^ unexpected syntax + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/index.snap b/crates/uitest/fixtures/parser/index.snap index ac5fc0646..edbface33 100644 --- a/crates/uitest/fixtures/parser/index.snap +++ b/crates/uitest/fixtures/parser/index.snap @@ -3,13 +3,13 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/index.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing index expression ┌─ index.fe:2:5 │ 2 │ x[1 a] - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: expected `]` +error[1-0001]: missing closing `]` for index expression ┌─ index.fe:3:8 │ 3 │ x[2 + 3 diff --git a/crates/uitest/fixtures/parser/match_.snap b/crates/uitest/fixtures/parser/match_.snap index 6e8f2ce14..85a9fbc3e 100644 --- a/crates/uitest/fixtures/parser/match_.snap +++ b/crates/uitest/fixtures/parser/match_.snap @@ -3,11 +3,11 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/match_.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `match` expression ┌─ match_.fe:2:10 │ 2 │ match X => { - │ ^^ unexpected syntax + │ ^^ unexpected error[1-0001]: expected `=>` ┌─ match_.fe:4:7 @@ -16,21 +16,15 @@ error[1-0001]: expected `=>` │ ^ expected `=>` error[1-0001]: expected pattern - ┌─ match_.fe:8:16 + ┌─ match_.fe:8:13 │ 8 │ Foo(i, j, => true x - │ ^ expected pattern + │ ^ expected pattern -error[1-0001]: expected `)` - ┌─ match_.fe:8:16 - │ -8 │ Foo(i, j, => true x - │ ^ expected `)` - -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `match` arm list ┌─ match_.fe:8:24 │ 8 │ Foo(i, j, => true x - │ ^ unexpected syntax + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/method.snap b/crates/uitest/fixtures/parser/method.snap index b1097ffbb..dea18a27a 100644 --- a/crates/uitest/fixtures/parser/method.snap +++ b/crates/uitest/fixtures/parser/method.snap @@ -3,28 +3,16 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/method.fe --- -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing generic type argument list ┌─ method.fe:2:23 │ 2 │ foo::bar.baz(1, 2) - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: expected path segment - ┌─ method.fe:2:25 - │ -2 │ foo::bar.baz(1, 2) - │ ^ expected path segment - -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing function call arguments ┌─ method.fe:4:17 │ 4 │ foo::bar.x(1, 2 E,) - │ ^ unexpected syntax - -error[1-0001]: expected expression - ┌─ method.fe:4:19 - │ -4 │ foo::bar.x(1, 2 E,) - │ ^ expected expression + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/operators.snap b/crates/uitest/fixtures/parser/operators.snap index 6a1ab56ff..d15e9a7f4 100644 --- a/crates/uitest/fixtures/parser/operators.snap +++ b/crates/uitest/fixtures/parser/operators.snap @@ -9,11 +9,11 @@ error[1-0001]: expected expression 3 │ x + = 1 │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing binary expression ┌─ operators.fe:3:9 │ 3 │ x + = 1 - │ ^^^ unexpected syntax + │ ^^^ unexpected error[1-0001]: expected expression ┌─ operators.fe:5:8 @@ -21,11 +21,11 @@ error[1-0001]: expected expression 5 │ x - = 1 │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing binary expression ┌─ operators.fe:5:12 │ 5 │ x - = 1 - │ ^^^ unexpected syntax + │ ^^^ unexpected error[1-0001]: expected expression ┌─ operators.fe:6:8 @@ -33,11 +33,11 @@ error[1-0001]: expected expression 6 │ x * = 1 │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing binary expression ┌─ operators.fe:6:9 │ 6 │ x * = 1 - │ ^^^ unexpected syntax + │ ^^^ unexpected error[1-0001]: expected expression ┌─ operators.fe:8:8 @@ -45,11 +45,11 @@ error[1-0001]: expected expression 8 │ x < < 1 │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing binary expression ┌─ operators.fe:8:9 │ 8 │ x < < 1 - │ ^^^ unexpected syntax + │ ^^^ unexpected error[1-0001]: expected expression ┌─ operators.fe:10:8 @@ -57,10 +57,10 @@ error[1-0001]: expected expression 10 │ x < = 1 │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing binary expression ┌─ operators.fe:10:9 │ 10 │ x < = 1 - │ ^^^ unexpected syntax + │ ^^^ unexpected diff --git a/crates/uitest/fixtures/parser/struct_.snap b/crates/uitest/fixtures/parser/struct_.snap index 2fc4443c2..ac499b6e4 100644 --- a/crates/uitest/fixtures/parser/struct_.snap +++ b/crates/uitest/fixtures/parser/struct_.snap @@ -3,23 +3,23 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/struct_.fe --- -error[1-0001]: expected identifier +error[1-0001]: expected name for struct definition ┌─ struct_.fe:1:11 │ 1 │ pub struct` or `,` +error[1-0001]: missing closing `>` for generic parameter list ┌─ struct_.fe:1:16 │ 1 │ pub struct` or `,` -error[1-0001]: expected `:` for type bounds +error[1-0001]: missing type bound for `where` predicate ┌─ struct_.fe:2:8 │ 2 │ where T - │ ^ expected `:` for type bounds + │ ^ expected `:` error[1-0001]: expected `,` ┌─ struct_.fe:2:8 @@ -27,13 +27,13 @@ error[1-0001]: expected `,` 2 │ where T │ ^ expected `,` -error[1-0001]: expected `name: type` for the field definition +error[1-0001]: missing type bound for field ┌─ struct_.fe:6:8 │ 6 │ foo - │ ^ expected `name: type` for the field definition + │ ^ expected `:` -error[1-0001]: expected `}` or `,` +error[1-0001]: missing closing `}` for record field list ┌─ struct_.fe:6:8 │ 6 │ foo @@ -45,7 +45,7 @@ error[1-0001]: function definition in struct is not allowed 11 │ pub fn foo() -> i32 { │ ^^ function definition in struct is not allowed -error[1-0001]: expected `}` or `,` +error[1-0001]: missing closing `}` for record field list ┌─ struct_.fe:13:6 │ 13 │ } diff --git a/crates/uitest/fixtures/parser/struct_field_missing_comma.snap b/crates/uitest/fixtures/parser/struct_field_missing_comma.snap index 12ccdb42a..904c37621 100644 --- a/crates/uitest/fixtures/parser/struct_field_missing_comma.snap +++ b/crates/uitest/fixtures/parser/struct_field_missing_comma.snap @@ -3,7 +3,7 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/struct_field_missing_comma.fe --- -error[1-0001]: expected `}` or `,` +error[1-0001]: missing closing `}` for record field list ┌─ struct_field_missing_comma.fe:2:10 │ 2 │ x: u8 diff --git a/crates/uitest/fixtures/parser/trait_.snap b/crates/uitest/fixtures/parser/trait_.snap index 919f4a05d..305c3fdb5 100644 --- a/crates/uitest/fixtures/parser/trait_.snap +++ b/crates/uitest/fixtures/parser/trait_.snap @@ -15,10 +15,10 @@ error[1-0001]: expected `{`, `where` or `:` 5 │ trait Bar │ ^ expected `{`, `where` or `:` -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing generic parameter list ┌─ trait_.fe:9:11 │ 9 │ trait Bar< - │ ^ unexpected syntax + │ ^ unexpected diff --git a/crates/uitest/fixtures/parser/trait_pub_fn.snap b/crates/uitest/fixtures/parser/trait_pub_fn.snap index 16075bfc9..7cf14e7b3 100644 --- a/crates/uitest/fixtures/parser/trait_pub_fn.snap +++ b/crates/uitest/fixtures/parser/trait_pub_fn.snap @@ -3,22 +3,22 @@ source: crates/uitest/tests/parser.rs expression: diags input_file: crates/uitest/fixtures/parser/trait_pub_fn.fe --- -error[1-0001]: modifier is not allowed in this block +error[1-0001]: `pub` modifier is not allowed in this block ┌─ trait_pub_fn.fe:2:5 │ 2 │ pub fn foo(mut self) - │ ^^^ modifier is not allowed in this block + │ ^^^ unexpected -error[1-0001]: modifier is not allowed in this block +error[1-0001]: `pub` modifier is not allowed in this block ┌─ trait_pub_fn.fe:3:5 │ 3 │ pub unsafe fn bar(self) - │ ^^^ modifier is not allowed in this block + │ ^^^ unexpected -error[1-0001]: modifier is not allowed in this block +error[1-0001]: `unsafe` modifier is not allowed in this block ┌─ trait_pub_fn.fe:3:9 │ 3 │ pub unsafe fn bar(self) - │ ^^^^^^ modifier is not allowed in this block + │ ^^^^^^ unexpected diff --git a/crates/uitest/fixtures/parser/while_.snap b/crates/uitest/fixtures/parser/while_.snap index 3da7cf975..a8a480c2e 100644 --- a/crates/uitest/fixtures/parser/while_.snap +++ b/crates/uitest/fixtures/parser/while_.snap @@ -9,23 +9,17 @@ error[1-0001]: expected expression 2 │ while @ {} │ ^ expected expression -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing `while` statement ┌─ while_.fe:2:7 │ 2 │ while @ {} - │ ^ unexpected syntax + │ ^ unexpected -error[1-0001]: expected item: but got Some(WhileKw) - ┌─ while_.fe:8:1 - │ -8 │ while true {} - │ ^ expected item: but got Some(WhileKw) - -error[1-0001]: unexpected syntax +error[1-0001]: unexpected syntax while parsing item ┌─ while_.fe:8:1 │ 8 │ ╭ while true {} 9 │ │ } - │ ╰─^ unexpected syntax + │ ╰─^ unexpected diff --git a/crates/uitest/fixtures/ty/def/kind_bound.fe b/crates/uitest/fixtures/ty/def/kind_bound.fe index 40a88a27f..fef8948dc 100644 --- a/crates/uitest/fixtures/ty/def/kind_bound.fe +++ b/crates/uitest/fixtures/ty/def/kind_bound.fe @@ -4,7 +4,7 @@ pub struct Wrapper1 value: T } -// (* -> *) -> * -> * +// (* -> *) -> * -> * pub struct Wrapper2 where T: * -> * { @@ -14,7 +14,7 @@ where T: * -> * // ((* -> *) -> *) -> (* -> *) -> * pub struct Wrapper3 -where T: (* -> *) -> * -> * +where T: (* -> *) -> * -> *, U: * -> * { value: T diff --git a/crates/uitest/fixtures/ty/def/trait_def.fe b/crates/uitest/fixtures/ty/def/trait_def.fe index 8150bbd23..d86cd7d93 100644 --- a/crates/uitest/fixtures/ty/def/trait_def.fe +++ b/crates/uitest/fixtures/ty/def/trait_def.fe @@ -1,6 +1,6 @@ trait Clone {} -pub trait Trait -where T: * -> * +pub trait Trait +where T: * -> *, T: (* -> *) -> * { diff --git a/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.fe b/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.fe index 538944749..35dbbddd5 100644 --- a/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.fe +++ b/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.fe @@ -15,9 +15,9 @@ pub trait Foo2 { } impl Foo2 for i32 { - fn foo(self, t: T, u: U) - where - T: Bar + Baz + fn foo(self, t: T, u: U) + where + T: Bar + Baz, U: Bar {} } \ No newline at end of file diff --git a/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.snap b/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.snap index 3ec4a0a25..a56e79283 100644 --- a/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.snap +++ b/crates/uitest/fixtures/ty/trait_impl/impl_method_stricter_bound.snap @@ -12,7 +12,7 @@ error[6-0009]: impl method has stricter bound than the declared method in the tr error[6-0009]: impl method has stricter bound than the declared method in the trait ┌─ impl_method_stricter_bound.fe:18:8 │ -18 │ fn foo(self, t: T, u: U) +18 │ fn foo(self, t: T, u: U) │ ^^^ method has stricter bounds than the declared method in the trait: `T: Baz`, `U: Bar`