diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 54e95cf7c3d5..46e9c54dad65 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -11,7 +11,7 @@ use hir_def::{ }; use hir_expand::{hygiene::Hygiene, MacroDefId}; use hir_ty::db::HirDatabase; -use syntax::ast; +use syntax::{ast, AstNode}; use crate::{ Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam, @@ -147,8 +147,18 @@ fn resolve_doc_path( // FIXME AttrDefId::MacroDefId(_) => return None, }; - let path = ast::Path::parse(link).ok()?; - let modpath = ModPath::from_src(db.upcast(), path, &Hygiene::new_unhygienic())?; + + let modpath = { + let ast_path = ast::SourceFile::parse(&format!("type T = {};", link)) + .syntax_node() + .descendants() + .find_map(ast::Path::cast)?; + if ast_path.to_string() != link { + return None; + } + ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())? + }; + let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); let resolved = if resolved == PerNs::none() { resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)? diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 36e46a103c1b..383ad7f0c832 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs @@ -714,8 +714,7 @@ impl Attr { hygiene: &Hygiene, id: AttrId, ) -> Option { - let (parse, _) = - mbe::token_tree_to_syntax_node(tt, mbe::ParserEntryPoint::MetaItem).ok()?; + let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem).ok()?; let ast = ast::Meta::cast(parse.syntax_node())?; Self::from_src(db, ast, hygiene, id) diff --git a/crates/hir_expand/src/builtin_derive_macro.rs b/crates/hir_expand/src/builtin_derive_macro.rs index c20dae8e6f79..c1542f48f0e1 100644 --- a/crates/hir_expand/src/builtin_derive_macro.rs +++ b/crates/hir_expand/src/builtin_derive_macro.rs @@ -72,7 +72,7 @@ struct BasicAdtInfo { } fn parse_adt(tt: &tt::Subtree) -> Result { - let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::ParserEntryPoint::Items)?; // FragmentKind::Items doesn't parse attrs? + let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems)?; // FragmentKind::Items doesn't parse attrs? let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| { debug!("derive node didn't parse"); mbe::ExpandError::UnexpectedToken diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 747a19a50927..3369e3e5fedf 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs @@ -497,11 +497,11 @@ fn token_tree_to_syntax_node( expand_to: ExpandTo, ) -> Result<(Parse, mbe::TokenMap), ExpandError> { let entry_point = match expand_to { - ExpandTo::Statements => mbe::ParserEntryPoint::Statements, - ExpandTo::Items => mbe::ParserEntryPoint::Items, - ExpandTo::Pattern => mbe::ParserEntryPoint::Pattern, - ExpandTo::Type => mbe::ParserEntryPoint::Type, - ExpandTo::Expr => mbe::ParserEntryPoint::Expr, + ExpandTo::Statements => mbe::TopEntryPoint::MacroStmts, + ExpandTo::Items => mbe::TopEntryPoint::MacroItems, + ExpandTo::Pattern => mbe::TopEntryPoint::Pattern, + ExpandTo::Type => mbe::TopEntryPoint::Type, + ExpandTo::Expr => mbe::TopEntryPoint::Expr, }; mbe::token_tree_to_syntax_node(tt, entry_point) } diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index ea57c2c41012..1d29ad26307e 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs @@ -131,7 +131,7 @@ pub fn expand_eager_macro( let arg_file_id = arg_id; let parsed_args = diagnostic_sink - .result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::ParserEntryPoint::Expr))? + .result(mbe::token_tree_to_syntax_node(&parsed_args, mbe::TopEntryPoint::Expr))? .0; let result = eager_macro_recur( db, diff --git a/crates/ide_assists/src/handlers/remove_dbg.rs b/crates/ide_assists/src/handlers/remove_dbg.rs index b860a3b6da87..07dcfd967177 100644 --- a/crates/ide_assists/src/handlers/remove_dbg.rs +++ b/crates/ide_assists/src/handlers/remove_dbg.rs @@ -36,9 +36,8 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let input_expressions = input_expressions .into_iter() .filter_map(|(is_sep, group)| (!is_sep).then(|| group)) - .map(|mut tokens| ast::Expr::parse(&tokens.join(""))) - .collect::, _>>() - .ok()?; + .map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join(""))) + .collect::>>()?; let parent = macro_call.syntax().parent()?; let (range, text) = match &*input_expressions { diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index d763878834f6..f67d7d56d819 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs @@ -309,7 +309,7 @@ fn parse_comma_sep_expr(input: ast::TokenTree) -> Option> { input_expressions .into_iter() .filter_map(|(is_sep, group)| (!is_sep).then(|| group)) - .filter_map(|mut tokens| ast::Expr::parse(&tokens.join("")).ok()) + .filter_map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join(""))) .collect::>(), ) } diff --git a/crates/ide_completion/src/snippet.rs b/crates/ide_completion/src/snippet.rs index c5e2b009c7ce..98cd3f8f3370 100644 --- a/crates/ide_completion/src/snippet.rs +++ b/crates/ide_completion/src/snippet.rs @@ -212,15 +212,14 @@ fn validate_snippet( ) -> Option<(Box<[GreenNode]>, String, Option>)> { let mut imports = Vec::with_capacity(requires.len()); for path in requires.iter() { - let path = ast::Path::parse(path).ok()?; - let valid_use_path = path.segments().all(|seg| { - matches!(seg.kind(), Some(ast::PathSegmentKind::Name(_))) - || seg.generic_arg_list().is_none() - }); - if !valid_use_path { + let use_path = ast::SourceFile::parse(&format!("use {};", path)) + .syntax_node() + .descendants() + .find_map(ast::Path::cast)?; + if use_path.syntax().text() != path.as_str() { return None; } - let green = path.syntax().green().into_owned(); + let green = use_path.syntax().green().into_owned(); imports.push(green); } let snippet = snippet.iter().join("\n"); diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index e4199898bfc5..e589940dae29 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -67,7 +67,11 @@ pub fn get_path_at_cursor_in_tt(cursor: &ast::Ident) -> Option { .filter_map(SyntaxElement::into_token) .take_while(|tok| tok != cursor); - ast::Path::parse(&path_tokens.chain(iter::once(cursor.clone())).join("")).ok() + syntax::hacks::parse_expr_from_str(&path_tokens.chain(iter::once(cursor.clone())).join("")) + .and_then(|expr| match expr { + ast::Expr::PathExpr(it) => it.path(), + _ => None, + }) } /// Parses and resolves the path at the cursor position in the given attribute, if it is a derive. @@ -323,7 +327,12 @@ pub fn parse_tt_as_comma_sep_paths(input: ast::TokenTree) -> Option it.path(), + _ => None, + }) + }) .collect(); Some(paths) } diff --git a/crates/ide_ssr/src/fragments.rs b/crates/ide_ssr/src/fragments.rs new file mode 100644 index 000000000000..503754afe7c2 --- /dev/null +++ b/crates/ide_ssr/src/fragments.rs @@ -0,0 +1,58 @@ +//! When specifying SSR rule, you generally want to map one *kind* of thing to +//! the same kind of thing: path to path, expression to expression, type to +//! type. +//! +//! The problem is, while this *kind* is generally obvious to the human, the ide +//! needs to determine it somehow. We do this in a stupid way -- by pasting SSR +//! rule into different contexts and checking what works. + +use syntax::{ast, AstNode, SyntaxNode}; + +pub(crate) fn ty(s: &str) -> Result { + fragment::("type T = {};", s) +} + +pub(crate) fn item(s: &str) -> Result { + fragment::("{}", s) +} + +pub(crate) fn pat(s: &str) -> Result { + fragment::("const _: () = {let {} = ();};", s) +} + +pub(crate) fn expr(s: &str) -> Result { + fragment::("const _: () = {};", s) +} + +pub(crate) fn stmt(s: &str) -> Result { + let template = "const _: () = { {}; };"; + let input = template.replace("{}", s); + let parse = syntax::SourceFile::parse(&input); + if !parse.errors().is_empty() { + return Err(()); + } + let mut node = + parse.tree().syntax().descendants().skip(2).find_map(ast::Stmt::cast).ok_or(())?; + if !s.ends_with(';') && node.to_string().ends_with(';') { + node = node.clone_for_update(); + node.syntax().last_token().map(|it| it.detach()); + } + if node.to_string() != s { + return Err(()); + } + Ok(node.syntax().clone_subtree()) +} + +fn fragment(template: &str, s: &str) -> Result { + let s = s.trim(); + let input = template.replace("{}", s); + let parse = syntax::SourceFile::parse(&input); + if !parse.errors().is_empty() { + return Err(()); + } + let node = parse.tree().syntax().descendants().find_map(T::cast).ok_or(())?; + if node.syntax().text() != s { + return Err(()); + } + Ok(node.syntax().clone_subtree()) +} diff --git a/crates/ide_ssr/src/lib.rs b/crates/ide_ssr/src/lib.rs index 2fe1f5b616ed..d56bc12b680c 100644 --- a/crates/ide_ssr/src/lib.rs +++ b/crates/ide_ssr/src/lib.rs @@ -71,6 +71,7 @@ mod from_comment; mod matching; mod nester; mod parsing; +mod fragments; mod replacing; mod resolving; mod search; diff --git a/crates/ide_ssr/src/parsing.rs b/crates/ide_ssr/src/parsing.rs index ae7d5b4bf156..aaaee576b52b 100644 --- a/crates/ide_ssr/src/parsing.rs +++ b/crates/ide_ssr/src/parsing.rs @@ -4,12 +4,12 @@ //! placeholders, which start with `$`. For replacement templates, this is the final form. For //! search patterns, we go further and parse the pattern as each kind of thing that we can match. //! e.g. expressions, type references etc. - -use crate::errors::bail; -use crate::{SsrError, SsrPattern, SsrRule}; use rustc_hash::{FxHashMap, FxHashSet}; use std::{fmt::Display, str::FromStr}; -use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T}; +use syntax::{SmolStr, SyntaxKind, SyntaxNode, T}; + +use crate::errors::bail; +use crate::{fragments, SsrError, SsrPattern, SsrRule}; #[derive(Debug)] pub(crate) struct ParsedRule { @@ -73,17 +73,16 @@ impl ParsedRule { rules: Vec::new(), }; - let raw_template_stmt = raw_template.map(ast::Stmt::parse); - if let raw_template_expr @ Some(Ok(_)) = raw_template.map(ast::Expr::parse) { - builder.try_add(ast::Expr::parse(&raw_pattern), raw_template_expr); + let raw_template_stmt = raw_template.map(fragments::stmt); + if let raw_template_expr @ Some(Ok(_)) = raw_template.map(fragments::expr) { + builder.try_add(fragments::expr(&raw_pattern), raw_template_expr); } else { - builder.try_add(ast::Expr::parse(&raw_pattern), raw_template_stmt.clone()); + builder.try_add(fragments::expr(&raw_pattern), raw_template_stmt.clone()); } - builder.try_add(ast::Type::parse(&raw_pattern), raw_template.map(ast::Type::parse)); - builder.try_add(ast::Item::parse(&raw_pattern), raw_template.map(ast::Item::parse)); - builder.try_add(ast::Path::parse(&raw_pattern), raw_template.map(ast::Path::parse)); - builder.try_add(ast::Pat::parse(&raw_pattern), raw_template.map(ast::Pat::parse)); - builder.try_add(ast::Stmt::parse(&raw_pattern), raw_template_stmt); + builder.try_add(fragments::ty(&raw_pattern), raw_template.map(fragments::ty)); + builder.try_add(fragments::item(&raw_pattern), raw_template.map(fragments::item)); + builder.try_add(fragments::pat(&raw_pattern), raw_template.map(fragments::pat)); + builder.try_add(fragments::stmt(&raw_pattern), raw_template_stmt); builder.build() } } @@ -94,20 +93,20 @@ struct RuleBuilder { } impl RuleBuilder { - fn try_add( + fn try_add( &mut self, - pattern: Result, - template: Option>, + pattern: Result, + template: Option>, ) { match (pattern, template) { (Ok(pattern), Some(Ok(template))) => self.rules.push(ParsedRule { placeholders_by_stand_in: self.placeholders_by_stand_in.clone(), - pattern: pattern.syntax().clone(), - template: Some(template.syntax().clone()), + pattern, + template: Some(template), }), (Ok(pattern), None) => self.rules.push(ParsedRule { placeholders_by_stand_in: self.placeholders_by_stand_in.clone(), - pattern: pattern.syntax().clone(), + pattern, template: None, }), _ => {} diff --git a/crates/ide_ssr/src/replacing.rs b/crates/ide_ssr/src/replacing.rs index 9265af7c13a6..6d21bad1eb38 100644 --- a/crates/ide_ssr/src/replacing.rs +++ b/crates/ide_ssr/src/replacing.rs @@ -1,5 +1,6 @@ //! Code for applying replacement templates for matches that have previously been found. +use crate::fragments; use crate::{resolving::ResolvedRule, Match, SsrMatches}; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -225,12 +226,13 @@ fn token_is_method_call_receiver(token: &SyntaxToken) -> bool { fn parse_as_kind(code: &str, kind: SyntaxKind) -> Option { if ast::Expr::can_cast(kind) { - if let Ok(expr) = ast::Expr::parse(code) { - return Some(expr.syntax().clone()); + if let Ok(expr) = fragments::expr(code) { + return Some(expr); } - } else if ast::Item::can_cast(kind) { - if let Ok(item) = ast::Item::parse(code) { - return Some(item.syntax().clone()); + } + if ast::Item::can_cast(kind) { + if let Ok(item) = fragments::item(code) { + return Some(item); } } None diff --git a/crates/ide_ssr/src/tests.rs b/crates/ide_ssr/src/tests.rs index 0b0c1111c466..30eda9d56cb5 100644 --- a/crates/ide_ssr/src/tests.rs +++ b/crates/ide_ssr/src/tests.rs @@ -331,6 +331,15 @@ fn ssr_struct_lit() { ) } +#[test] +fn ssr_struct_def() { + assert_ssr_transform( + "struct Foo { $f: $t } ==>> struct Foo($t);", + r#"struct Foo { field: i32 }"#, + expect![[r#"struct Foo(i32);"#]], + ) +} + #[test] fn ignores_whitespace() { assert_matches("1+2", "fn f() -> i32 {1 + 2}", &["1 + 2"]); @@ -792,6 +801,19 @@ fn replace_type() { "struct Result {} struct Option {} fn f1() -> Option> {foo()}" ]], ); + assert_ssr_transform( + "dyn Trait<$a> ==>> DynTrait<$a>", + r#" +trait Trait {} +struct DynTrait {} +fn f1() -> dyn Trait> {foo()} +"#, + expect![[r#" +trait Trait {} +struct DynTrait {} +fn f1() -> DynTrait> {foo()} +"#]], + ); } #[test] diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index b2d3f038f544..bcda2381a486 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs @@ -61,18 +61,16 @@ use std::rc::Rc; +use smallvec::{smallvec, SmallVec}; +use syntax::SmolStr; + use crate::{ - expander::{Binding, Bindings, Fragment}, + expander::{Binding, Bindings, ExpandResult, Fragment}, parser::{Op, RepeatKind, Separator}, tt_iter::TtIter, ExpandError, MetaTemplate, }; -use super::ExpandResult; -use parser::ParserEntryPoint::*; -use smallvec::{smallvec, SmallVec}; -use syntax::SmolStr; - impl Bindings { fn push_optional(&mut self, name: &SmolStr) { // FIXME: Do we have a better way to represent an empty token ? @@ -691,14 +689,21 @@ fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter) -> Result<(), ExpandError> { fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult> { let fragment = match kind { - "path" => Path, - "expr" => Expr, - "ty" => Type, - "pat" | "pat_param" => Pattern, // FIXME: edition2021 - "stmt" => Statement, - "block" => Block, - "meta" => MetaItem, - "item" => Item, + "path" => parser::PrefixEntryPoint::Path, + "ty" => parser::PrefixEntryPoint::Ty, + // FIXME: These two should actually behave differently depending on the edition. + // + // https://doc.rust-lang.org/edition-guide/rust-2021/or-patterns-macro-rules.html + "pat" | "pat_param" => parser::PrefixEntryPoint::Pat, + "stmt" => parser::PrefixEntryPoint::Stmt, + "block" => parser::PrefixEntryPoint::Block, + "meta" => parser::PrefixEntryPoint::MetaItem, + "item" => parser::PrefixEntryPoint::Item, + "expr" => { + return input + .expect_fragment(parser::PrefixEntryPoint::Expr) + .map(|tt| tt.map(Fragment::Expr)) + } _ => { let tt_result = match kind { "ident" => input @@ -726,17 +731,13 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult match input.eat_vis() { - Some(vis) => Ok(Some(vis)), - None => Ok(None), - }, + "vis" => Ok(input.expect_fragment(parser::PrefixEntryPoint::Vis).value), _ => Err(ExpandError::UnexpectedToken), }; return tt_result.map(|it| it.map(Fragment::Tokens)).into(); } }; - let result = input.expect_fragment(fragment); - result.map(|tt| if kind == "expr" { tt.map(Fragment::Expr) } else { tt.map(Fragment::Tokens) }) + input.expect_fragment(fragment).map(|it| it.map(Fragment::Tokens)) } fn collect_vars(buf: &mut Vec, pattern: &MetaTemplate) { @@ -898,17 +899,6 @@ impl<'a> TtIter<'a> { .into()) } - fn eat_vis(&mut self) -> Option { - let mut fork = self.clone(); - match fork.expect_fragment(Visibility) { - ExpandResult { value: tt, err: None } => { - *self = fork; - tt - } - ExpandResult { value: _, err: Some(_) } => None, - } - } - fn eat_char(&mut self, c: char) -> Option { let mut fork = self.clone(); match fork.expect_char(c) { diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 5e14a3fb5902..62e7509eb37c 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -24,7 +24,7 @@ use crate::{ }; // FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces -pub use ::parser::ParserEntryPoint; +pub use ::parser::TopEntryPoint; pub use tt::{Delimiter, DelimiterKind, Punct}; #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index f0c1f806ffae..8bdc5e6e9463 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -9,9 +9,7 @@ use syntax::{ }; use tt::buffer::{Cursor, TokenBuffer}; -use crate::{ - to_parser_input::to_parser_input, tt_iter::TtIter, ExpandError, ParserEntryPoint, TokenMap, -}; +use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, ExpandError, TokenMap}; /// Convert the syntax node to a `TokenTree` (what macro /// will consume). @@ -46,7 +44,7 @@ pub fn syntax_node_to_token_tree_censored( pub fn token_tree_to_syntax_node( tt: &tt::Subtree, - entry_point: ParserEntryPoint, + entry_point: parser::TopEntryPoint, ) -> Result<(Parse, TokenMap), ExpandError> { let buffer = match tt { tt::Subtree { delimiter: None, token_trees } => { @@ -55,7 +53,7 @@ pub fn token_tree_to_syntax_node( _ => TokenBuffer::from_subtree(tt), }; let parser_input = to_parser_input(&buffer); - let parser_output = parser::parse(&parser_input, entry_point); + let parser_output = entry_point.parse(&parser_input); let mut tree_sink = TtTreeSink::new(buffer.begin()); for event in parser_output.iter() { match event { @@ -106,7 +104,7 @@ pub fn parse_exprs_with_sep(tt: &tt::Subtree, sep: char) -> Vec { let mut res = Vec::new(); while iter.peek_n(0).is_some() { - let expanded = iter.expect_fragment(ParserEntryPoint::Expr); + let expanded = iter.expect_fragment(parser::PrefixEntryPoint::Expr); res.push(match expanded.value { None => break, diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs index 2d2dbd8994f6..6c9f615c7a92 100644 --- a/crates/mbe/src/tt_iter.rs +++ b/crates/mbe/src/tt_iter.rs @@ -1,7 +1,7 @@ //! A "Parser" structure for token trees. We use this when parsing a declarative //! macro definition into a list of patterns and templates. -use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult, ParserEntryPoint}; +use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult}; use syntax::SyntaxKind; use tt::buffer::TokenBuffer; @@ -91,11 +91,11 @@ impl<'a> TtIter<'a> { pub(crate) fn expect_fragment( &mut self, - entry_point: ParserEntryPoint, + entry_point: parser::PrefixEntryPoint, ) -> ExpandResult> { let buffer = TokenBuffer::from_tokens(self.inner.as_slice()); let parser_input = to_parser_input(&buffer); - let tree_traversal = parser::parse(&parser_input, entry_point); + let tree_traversal = entry_point.parse(&parser_input); let mut cursor = buffer.begin(); let mut error = false; diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs index 25178ddd775a..42426a1df285 100644 --- a/crates/parser/src/grammar.rs +++ b/crates/parser/src/grammar.rs @@ -44,72 +44,76 @@ use crate::{ TokenSet, T, }; -pub(crate) mod entry_points { +pub(crate) mod entry { use super::*; - pub(crate) fn source_file(p: &mut Parser) { - let m = p.start(); - p.eat(SHEBANG); - items::mod_contents(p, false); - m.complete(p, SOURCE_FILE); - } - - pub(crate) use expressions::block_expr; - - pub(crate) use paths::type_path as path; + pub(crate) mod prefix { + use super::*; - pub(crate) use patterns::pattern_single as pattern; - - pub(crate) use types::type_; + pub(crate) fn vis(p: &mut Parser) { + let _ = opt_visibility(p, false); + } - pub(crate) fn expr(p: &mut Parser) { - let _ = expressions::expr(p); - } + pub(crate) fn block(p: &mut Parser) { + expressions::block_expr(p); + } - pub(crate) fn stmt(p: &mut Parser) { - expressions::stmt(p, expressions::StmtWithSemi::No, true); - } + pub(crate) fn stmt(p: &mut Parser) { + expressions::stmt(p, expressions::StmtWithSemi::No, true); + } - pub(crate) fn stmt_optional_semi(p: &mut Parser) { - expressions::stmt(p, expressions::StmtWithSemi::Optional, false); - } + pub(crate) fn pat(p: &mut Parser) { + patterns::pattern_single(p); + } - pub(crate) fn visibility(p: &mut Parser) { - let _ = opt_visibility(p, false); + pub(crate) fn ty(p: &mut Parser) { + types::type_(p); + } + pub(crate) fn expr(p: &mut Parser) { + let _ = expressions::expr(p); + } + pub(crate) fn path(p: &mut Parser) { + let _ = paths::type_path(p); + } + pub(crate) fn item(p: &mut Parser) { + items::item_or_macro(p, true); + } + // Parse a meta item , which excluded [], e.g : #[ MetaItem ] + pub(crate) fn meta_item(p: &mut Parser) { + attributes::meta(p); + } } - // Parse a meta item , which excluded [], e.g : #[ MetaItem ] - pub(crate) fn meta_item(p: &mut Parser) { - attributes::meta(p); - } + pub(crate) mod top { + use super::*; - pub(crate) fn item(p: &mut Parser) { - items::item_or_macro(p, true); - } + pub(crate) fn source_file(p: &mut Parser) { + let m = p.start(); + p.eat(SHEBANG); + items::mod_contents(p, false); + m.complete(p, SOURCE_FILE); + } - pub(crate) fn macro_items(p: &mut Parser) { - let m = p.start(); - items::mod_contents(p, false); - m.complete(p, MACRO_ITEMS); - } + pub(crate) fn macro_stmts(p: &mut Parser) { + let m = p.start(); - pub(crate) fn macro_stmts(p: &mut Parser) { - let m = p.start(); + while !p.at(EOF) { + if p.at(T![;]) { + p.bump(T![;]); + continue; + } - while !p.at(EOF) { - if p.at(T![;]) { - p.bump(T![;]); - continue; + expressions::stmt(p, expressions::StmtWithSemi::Optional, true); } - expressions::stmt(p, expressions::StmtWithSemi::Optional, true); + m.complete(p, MACRO_STMTS); } - m.complete(p, MACRO_STMTS); - } - - pub(crate) fn attr(p: &mut Parser) { - attributes::outer_attrs(p); + pub(crate) fn macro_items(p: &mut Parser) { + let m = p.start(); + items::mod_contents(p, false); + m.complete(p, MACRO_ITEMS); + } } } diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 841d2aa4e946..c5014be6c336 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -41,63 +41,95 @@ pub use crate::{ syntax_kind::SyntaxKind, }; -/// rust-analyzer parser allows you to choose one of the possible entry points. +/// Parse a prefix of the input as a given syntactic construct. /// -/// The primary consumer of this API are declarative macros, `$x:expr` matchers -/// are implemented by calling into the parser with non-standard entry point. -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub enum ParserEntryPoint { - SourceFile, - Path, +/// This is used by macro-by-example parser to implement things like `$i:item` +/// and the naming of variants follows the naming of macro fragments. +/// +/// Note that this is generally non-optional -- the result is intentionally not +/// `Option`. The way MBE work, by the time we *try* to parse `$e:expr` +/// we already commit to expression. In other words, this API by design can't be +/// used to implement "rollback and try another alternative" logic. +#[derive(Debug)] +pub enum PrefixEntryPoint { + Vis, + Block, + Stmt, + Pat, + Ty, Expr, - Statement, - StatementOptionalSemi, - Type, - Pattern, + Path, Item, - Block, - Visibility, MetaItem, - Items, - Statements, - Attr, } -/// Parse given tokens into the given sink as a rust file. -pub fn parse_source_file(inp: &Input) -> Output { - parse(inp, ParserEntryPoint::SourceFile) +impl PrefixEntryPoint { + pub fn parse(&self, input: &Input) -> Output { + let entry_point: fn(&'_ mut parser::Parser) = match self { + PrefixEntryPoint::Vis => grammar::entry::prefix::vis, + PrefixEntryPoint::Block => grammar::entry::prefix::block, + PrefixEntryPoint::Stmt => grammar::entry::prefix::stmt, + PrefixEntryPoint::Pat => grammar::entry::prefix::pat, + PrefixEntryPoint::Ty => grammar::entry::prefix::ty, + PrefixEntryPoint::Expr => grammar::entry::prefix::expr, + PrefixEntryPoint::Path => grammar::entry::prefix::path, + PrefixEntryPoint::Item => grammar::entry::prefix::item, + PrefixEntryPoint::MetaItem => grammar::entry::prefix::meta_item, + }; + let mut p = parser::Parser::new(input); + entry_point(&mut p); + let events = p.finish(); + event::process(events) + } } -/// Parses the given [`Input`] into [`Output`] assuming that the top-level -/// syntactic construct is the given [`ParserEntryPoint`]. +/// Parse the whole of the input as a given syntactic construct. +/// +/// This covers two main use-cases: +/// +/// * Parsing a Rust file. +/// * Parsing a result of macro expansion. /// -/// Both input and output here are fairly abstract. The overall flow is that the -/// caller has some "real" tokens, converts them to [`Input`], parses them to -/// [`Output`], and then converts that into a "real" tree. The "real" tree is -/// made of "real" tokens, so this all hinges on rather tight coordination of -/// indices between the four stages. -pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output { - let entry_point: fn(&'_ mut parser::Parser) = match entry_point { - ParserEntryPoint::SourceFile => grammar::entry_points::source_file, - ParserEntryPoint::Path => grammar::entry_points::path, - ParserEntryPoint::Expr => grammar::entry_points::expr, - ParserEntryPoint::Type => grammar::entry_points::type_, - ParserEntryPoint::Pattern => grammar::entry_points::pattern, - ParserEntryPoint::Item => grammar::entry_points::item, - ParserEntryPoint::Block => grammar::entry_points::block_expr, - ParserEntryPoint::Visibility => grammar::entry_points::visibility, - ParserEntryPoint::MetaItem => grammar::entry_points::meta_item, - ParserEntryPoint::Statement => grammar::entry_points::stmt, - ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi, - ParserEntryPoint::Items => grammar::entry_points::macro_items, - ParserEntryPoint::Statements => grammar::entry_points::macro_stmts, - ParserEntryPoint::Attr => grammar::entry_points::attr, - }; +/// That is, for something like +/// +/// ``` +/// quick_check! { +/// fn prop() {} +/// } +/// ``` +/// +/// the input to the macro will be parsed with [`PrefixEntryPoint::Item`], and +/// the result will be [`TopEntryPoint::Items`]. +/// +/// This *should* (but currently doesn't) guarantee that all input is consumed. +#[derive(Debug)] +pub enum TopEntryPoint { + SourceFile, + MacroStmts, + MacroItems, + Pattern, + Type, + Expr, + MetaItem, +} - let mut p = parser::Parser::new(inp); - entry_point(&mut p); - let events = p.finish(); - event::process(events) +impl TopEntryPoint { + pub fn parse(&self, input: &Input) -> Output { + let entry_point: fn(&'_ mut parser::Parser) = match self { + TopEntryPoint::SourceFile => grammar::entry::top::source_file, + TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts, + TopEntryPoint::MacroItems => grammar::entry::top::macro_items, + // FIXME + TopEntryPoint::Pattern => grammar::entry::prefix::pat, + TopEntryPoint::Type => grammar::entry::prefix::ty, + TopEntryPoint::Expr => grammar::entry::prefix::expr, + TopEntryPoint::MetaItem => grammar::entry::prefix::meta_item, + }; + let mut p = parser::Parser::new(input); + entry_point(&mut p); + let events = p.finish(); + event::process(events) + } } /// A parsing function for a specific braced-block. diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs index 15387a85cc16..3d28f814c9f2 100644 --- a/crates/parser/src/shortcuts.rs +++ b/crates/parser/src/shortcuts.rs @@ -52,14 +52,10 @@ impl<'a> LexedStr<'a> { pub fn intersperse_trivia( &self, output: &crate::Output, - synthetic_root: bool, sink: &mut dyn FnMut(StrStep), ) -> bool { let mut builder = Builder { lexed: self, pos: 0, state: State::PendingEnter, sink }; - if synthetic_root { - builder.enter(SyntaxKind::SOURCE_FILE); - } for event in output.iter() { match event { Step::Token { kind, n_input_tokens: n_raw_tokens } => { @@ -73,9 +69,6 @@ impl<'a> LexedStr<'a> { } } } - if synthetic_root { - builder.exit(); - } match mem::replace(&mut builder.state, State::Normal) { State::PendingExit => { diff --git a/crates/parser/src/tests.rs b/crates/parser/src/tests.rs index 7a6230eaf8b2..512f7ddb95bb 100644 --- a/crates/parser/src/tests.rs +++ b/crates/parser/src/tests.rs @@ -80,12 +80,12 @@ fn parse_inline_err() { fn parse(text: &str) -> (String, bool) { let lexed = LexedStr::new(text); let input = lexed.to_input(); - let output = crate::parse_source_file(&input); + let output = crate::TopEntryPoint::SourceFile.parse(&input); let mut buf = String::new(); let mut errors = Vec::new(); let mut indent = String::new(); - lexed.intersperse_trivia(&output, false, &mut |step| match step { + lexed.intersperse_trivia(&output, &mut |step| match step { crate::StrStep::Token { kind, text } => { write!(buf, "{}", indent).unwrap(); write!(buf, "{:?} {:?}\n", kind, text).unwrap(); diff --git a/crates/syntax/src/hacks.rs b/crates/syntax/src/hacks.rs new file mode 100644 index 000000000000..a047f61fa03c --- /dev/null +++ b/crates/syntax/src/hacks.rs @@ -0,0 +1,15 @@ +//! Things which exist to solve practial issues, but which shouldn't exist. +//! +//! Please avoid adding new usages of the functions in this module + +use crate::{ast, AstNode}; + +pub fn parse_expr_from_str(s: &str) -> Option { + let s = s.trim(); + let file = ast::SourceFile::parse(&format!("const _: () = {};", s)); + let expr = file.syntax_node().descendants().find_map(ast::Expr::cast)?; + if expr.syntax().text() != s { + return None; + } + Some(expr) +} diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 65a6b7ac4e4a..d6b1cce45ff7 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -40,6 +40,7 @@ pub mod ast; pub mod fuzz; pub mod utils; pub mod ted; +pub mod hacks; use std::{marker::PhantomData, sync::Arc}; @@ -167,61 +168,6 @@ impl SourceFile { } } -// FIXME: `parse` functions shouldn't hang directly from AST nodes, and they -// shouldn't return `Result`. -// -// We need a dedicated module for parser entry points, and they should always -// return `Parse`. - -impl ast::Path { - /// Returns `text`, parsed as a path, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Path) - } -} - -impl ast::Pat { - /// Returns `text`, parsed as a pattern, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Pattern) - } -} - -impl ast::Expr { - /// Returns `text`, parsed as an expression, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Expr) - } -} - -impl ast::Item { - /// Returns `text`, parsed as an item, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Item) - } -} - -impl ast::Type { - /// Returns `text`, parsed as an type reference, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Type) - } -} - -impl ast::Attr { - /// Returns `text`, parsed as an attribute, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::Attr) - } -} - -impl ast::Stmt { - /// Returns `text`, parsed as statement, but only if it has no errors. - pub fn parse(text: &str) -> Result { - parsing::parse_text_as(text, parser::ParserEntryPoint::StatementOptionalSemi) - } -} - /// Matches a `SyntaxNode` against an `ast` type. /// /// # Example: diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs index 971fa2700d2f..047e670c9f45 100644 --- a/crates/syntax/src/parsing.rs +++ b/crates/syntax/src/parsing.rs @@ -5,46 +5,25 @@ mod reparsing; use rowan::TextRange; -use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode, SyntaxTreeBuilder}; +use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder}; pub(crate) use crate::parsing::reparsing::incremental_reparse; pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec) { let lexed = parser::LexedStr::new(text); let parser_input = lexed.to_input(); - let parser_output = parser::parse_source_file(&parser_input); - let (node, errors, _eof) = build_tree(lexed, parser_output, false); + let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input); + let (node, errors, _eof) = build_tree(lexed, parser_output); (node, errors) } -/// Returns `text` parsed as a `T` provided there are no parse errors. -pub(crate) fn parse_text_as( - text: &str, - entry_point: parser::ParserEntryPoint, -) -> Result { - let lexed = parser::LexedStr::new(text); - if lexed.errors().next().is_some() { - return Err(()); - } - let parser_input = lexed.to_input(); - let parser_output = parser::parse(&parser_input, entry_point); - let (node, errors, eof) = build_tree(lexed, parser_output, true); - - if !errors.is_empty() || !eof { - return Err(()); - } - - SyntaxNode::new_root(node).first_child().and_then(T::cast).ok_or(()) -} - pub(crate) fn build_tree( lexed: parser::LexedStr<'_>, parser_output: parser::Output, - synthetic_root: bool, ) -> (GreenNode, Vec, bool) { let mut builder = SyntaxTreeBuilder::default(); - let is_eof = lexed.intersperse_trivia(&parser_output, synthetic_root, &mut |step| match step { + let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step { parser::StrStep::Token { kind, text } => builder.token(kind, text), parser::StrStep::Enter { kind } => builder.start_node(kind), parser::StrStep::Exit => builder.finish_node(), diff --git a/crates/syntax/src/parsing/reparsing.rs b/crates/syntax/src/parsing/reparsing.rs index dd2e01bfc4ca..701e6232d589 100644 --- a/crates/syntax/src/parsing/reparsing.rs +++ b/crates/syntax/src/parsing/reparsing.rs @@ -96,7 +96,7 @@ fn reparse_block( let tree_traversal = reparser.parse(&parser_input); - let (green, new_parser_errors, _eof) = build_tree(lexed, tree_traversal, false); + let (green, new_parser_errors, _eof) = build_tree(lexed, tree_traversal); Some((node.replace_with(green), new_parser_errors, node.text_range())) } diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 04105dedc9ed..0611143e2afe 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -59,60 +59,6 @@ fn validation_tests() { }); } -#[test] -fn expr_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/expr/ok"], - &["parser/fragments/expr/err"], - crate::ast::Expr::parse, - ); -} - -#[test] -fn path_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/path/ok"], - &["parser/fragments/path/err"], - crate::ast::Path::parse, - ); -} - -#[test] -fn pattern_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/pattern/ok"], - &["parser/fragments/pattern/err"], - crate::ast::Pat::parse, - ); -} - -#[test] -fn item_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/item/ok"], - &["parser/fragments/item/err"], - crate::ast::Item::parse, - ); -} - -#[test] -fn type_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/type/ok"], - &["parser/fragments/type/err"], - crate::ast::Type::parse, - ); -} - -#[test] -fn stmt_parser_tests() { - fragment_parser_dir_test( - &["parser/fragments/stmt/ok"], - &["parser/fragments/stmt/err"], - crate::ast::Stmt::parse, - ); -} - #[test] fn parser_fuzz_tests() { for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) { @@ -172,24 +118,6 @@ fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) { assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display()); } -fn fragment_parser_dir_test(ok_paths: &[&str], err_paths: &[&str], f: F) -where - T: crate::AstNode, - F: Fn(&str) -> Result, -{ - dir_tests(&test_data_dir(), ok_paths, "rast", |text, path| match f(text) { - Ok(node) => format!("{:#?}", crate::ast::AstNode::syntax(&node)), - Err(_) => panic!("Failed to parse '{:?}'", path), - }); - dir_tests(&test_data_dir(), err_paths, "rast", |text, path| { - if f(text).is_ok() { - panic!("'{:?}' successfully parsed when it should have errored", path); - } else { - "ERROR\n".to_owned() - } - }); -} - /// Calls callback `f` with input code and file paths for each `.rs` file in `test_data_dir` /// subdirectories defined by `paths`. /// diff --git a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs b/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs deleted file mode 100644 index ca49acb079e2..000000000000 --- a/crates/syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs +++ /dev/null @@ -1 +0,0 @@ -1 + diff --git a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast deleted file mode 100644 index fa78a02a6bf4..000000000000 --- a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rast +++ /dev/null @@ -1,8 +0,0 @@ -BIN_EXPR@0..5 - LITERAL@0..1 - INT_NUMBER@0..1 "1" - WHITESPACE@1..2 " " - PLUS@2..3 "+" - WHITESPACE@3..4 " " - LITERAL@4..5 - INT_NUMBER@4..5 "2" diff --git a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs b/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs deleted file mode 100644 index e0ef5840209c..000000000000 --- a/crates/syntax/test_data/parser/fragments/expr/ok/0000_add.rs +++ /dev/null @@ -1 +0,0 @@ -1 + 2 diff --git a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs b/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs deleted file mode 100644 index dc32389bbb79..000000000000 --- a/crates/syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs +++ /dev/null @@ -1 +0,0 @@ -fn fn foo() {} diff --git a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast deleted file mode 100644 index 4ff9967beac9..000000000000 --- a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rast +++ /dev/null @@ -1,13 +0,0 @@ -FN@0..11 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..11 - STMT_LIST@9..11 - L_CURLY@9..10 "{" - R_CURLY@10..11 "}" diff --git a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs b/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs deleted file mode 100644 index 8f3b7ef112a0..000000000000 --- a/crates/syntax/test_data/parser/fragments/item/ok/0000_fn.rs +++ /dev/null @@ -1 +0,0 @@ -fn foo() {} diff --git a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs b/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs deleted file mode 100644 index 2046de04929f..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs +++ /dev/null @@ -1 +0,0 @@ -struct diff --git a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs b/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs deleted file mode 100644 index 745e8d376f74..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/err/0001_expression.rs +++ /dev/null @@ -1 +0,0 @@ -a + b diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast deleted file mode 100644 index 0c5d4360fa8d..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast +++ /dev/null @@ -1,4 +0,0 @@ -PATH@0..3 - PATH_SEGMENT@0..3 - NAME_REF@0..3 - IDENT@0..3 "foo" diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs b/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs deleted file mode 100644 index 257cc5642cb1..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast deleted file mode 100644 index 4a2b45e6a968..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rast +++ /dev/null @@ -1,14 +0,0 @@ -PATH@0..13 - PATH@0..8 - PATH@0..3 - PATH_SEGMENT@0..3 - NAME_REF@0..3 - IDENT@0..3 "foo" - COLON2@3..5 "::" - PATH_SEGMENT@5..8 - NAME_REF@5..8 - IDENT@5..8 "bar" - COLON2@8..10 "::" - PATH_SEGMENT@10..13 - NAME_REF@10..13 - IDENT@10..13 "baz" diff --git a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs b/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs deleted file mode 100644 index 81e0b21cd410..000000000000 --- a/crates/syntax/test_data/parser/fragments/path/ok/0001_multipart.rs +++ /dev/null @@ -1 +0,0 @@ -foo::bar::baz diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs b/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs deleted file mode 100644 index ae26fc455660..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs +++ /dev/null @@ -1 +0,0 @@ -fn diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs b/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs deleted file mode 100644 index 61a391d08460..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs +++ /dev/null @@ -1 +0,0 @@ -Some(x diff --git a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast deleted file mode 100644 index dcf102339aa9..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast +++ /dev/null @@ -1,10 +0,0 @@ -TUPLE_STRUCT_PAT@0..7 - PATH@0..4 - PATH_SEGMENT@0..4 - NAME_REF@0..4 - IDENT@0..4 "Some" - L_PAREN@4..5 "(" - IDENT_PAT@5..6 - NAME@5..6 - IDENT@5..6 "x" - R_PAREN@6..7 ")" diff --git a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs b/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs deleted file mode 100644 index 87114dd78814..000000000000 --- a/crates/syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs +++ /dev/null @@ -1 +0,0 @@ -Some(x) diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs deleted file mode 100644 index 988df0705979..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs +++ /dev/null @@ -1 +0,0 @@ -#[foo] diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs deleted file mode 100644 index 7e3b2fd49367..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs +++ /dev/null @@ -1 +0,0 @@ -a(); b(); c() diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs deleted file mode 100644 index 2d06f376636f..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs +++ /dev/null @@ -1 +0,0 @@ -( diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs deleted file mode 100644 index 092bc2b04126..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs +++ /dev/null @@ -1 +0,0 @@ -; diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs deleted file mode 100644 index ca49acb079e2..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs +++ /dev/null @@ -1 +0,0 @@ -1 + diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast deleted file mode 100644 index 274fdf16deb9..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast +++ /dev/null @@ -1,9 +0,0 @@ -EXPR_STMT@0..5 - BIN_EXPR@0..5 - LITERAL@0..1 - INT_NUMBER@0..1 "1" - WHITESPACE@1..2 " " - PLUS@2..3 "+" - WHITESPACE@3..4 " " - LITERAL@4..5 - INT_NUMBER@4..5 "1" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs deleted file mode 100644 index 8d2f0971e2ce..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs +++ /dev/null @@ -1 +0,0 @@ -1 + 1 diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast deleted file mode 100644 index a2d4f18988a9..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast +++ /dev/null @@ -1,70 +0,0 @@ -EXPR_STMT@0..55 - BLOCK_EXPR@0..55 - STMT_LIST@0..55 - L_CURLY@0..1 "{" - WHITESPACE@1..6 "\n " - LET_STMT@6..20 - LET_KW@6..9 "let" - WHITESPACE@9..10 " " - IDENT_PAT@10..11 - NAME@10..11 - IDENT@10..11 "x" - WHITESPACE@11..12 " " - EQ@12..13 "=" - WHITESPACE@13..14 " " - CALL_EXPR@14..19 - PATH_EXPR@14..17 - PATH@14..17 - PATH_SEGMENT@14..17 - NAME_REF@14..17 - IDENT@14..17 "foo" - ARG_LIST@17..19 - L_PAREN@17..18 "(" - R_PAREN@18..19 ")" - SEMICOLON@19..20 ";" - WHITESPACE@20..25 "\n " - LET_STMT@25..39 - LET_KW@25..28 "let" - WHITESPACE@28..29 " " - IDENT_PAT@29..30 - NAME@29..30 - IDENT@29..30 "y" - WHITESPACE@30..31 " " - EQ@31..32 "=" - WHITESPACE@32..33 " " - CALL_EXPR@33..38 - PATH_EXPR@33..36 - PATH@33..36 - PATH_SEGMENT@33..36 - NAME_REF@33..36 - IDENT@33..36 "bar" - ARG_LIST@36..38 - L_PAREN@36..37 "(" - R_PAREN@37..38 ")" - SEMICOLON@38..39 ";" - WHITESPACE@39..44 "\n " - CALL_EXPR@44..53 - PATH_EXPR@44..46 - PATH@44..46 - PATH_SEGMENT@44..46 - NAME_REF@44..46 - IDENT@44..46 "Ok" - ARG_LIST@46..53 - L_PAREN@46..47 "(" - BIN_EXPR@47..52 - PATH_EXPR@47..48 - PATH@47..48 - PATH_SEGMENT@47..48 - NAME_REF@47..48 - IDENT@47..48 "x" - WHITESPACE@48..49 " " - PLUS@49..50 "+" - WHITESPACE@50..51 " " - PATH_EXPR@51..52 - PATH@51..52 - PATH_SEGMENT@51..52 - NAME_REF@51..52 - IDENT@51..52 "y" - R_PAREN@52..53 ")" - WHITESPACE@53..54 "\n" - R_CURLY@54..55 "}" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs deleted file mode 100644 index ffa5c1e66ef6..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs +++ /dev/null @@ -1,5 +0,0 @@ -{ - let x = foo(); - let y = bar(); - Ok(x + y) -} diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast deleted file mode 100644 index 8c186da93eed..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast +++ /dev/null @@ -1,11 +0,0 @@ -EXPR_STMT@0..6 - CALL_EXPR@0..5 - PATH_EXPR@0..3 - PATH@0..3 - PATH_SEGMENT@0..3 - NAME_REF@0..3 - IDENT@0..3 "foo" - ARG_LIST@3..5 - L_PAREN@3..4 "(" - R_PAREN@4..5 ")" - SEMICOLON@5..6 ";" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs deleted file mode 100644 index a280f9a5cce6..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs +++ /dev/null @@ -1 +0,0 @@ -foo(); diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast deleted file mode 100644 index 8ab38da21cb5..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast +++ /dev/null @@ -1,12 +0,0 @@ -LET_STMT@0..11 - LET_KW@0..3 "let" - WHITESPACE@3..4 " " - IDENT_PAT@4..5 - NAME@4..5 - IDENT@4..5 "x" - WHITESPACE@5..6 " " - EQ@6..7 "=" - WHITESPACE@7..8 " " - LITERAL@8..10 - INT_NUMBER@8..10 "10" - SEMICOLON@10..11 ";" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs deleted file mode 100644 index de8a7f1fc6c4..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs +++ /dev/null @@ -1 +0,0 @@ -let x = 10; diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast deleted file mode 100644 index 81d6df29a5fb..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast +++ /dev/null @@ -1,21 +0,0 @@ -EXPR_STMT@0..18 - MACRO_CALL@0..17 - PATH@0..2 - PATH_SEGMENT@0..2 - NAME_REF@0..2 - IDENT@0..2 "m1" - BANG@2..3 "!" - TOKEN_TREE@3..17 - L_CURLY@3..4 "{" - WHITESPACE@4..5 " " - LET_KW@5..8 "let" - WHITESPACE@8..9 " " - IDENT@9..10 "a" - WHITESPACE@10..11 " " - EQ@11..12 "=" - WHITESPACE@12..13 " " - INT_NUMBER@13..14 "0" - SEMICOLON@14..15 ";" - WHITESPACE@15..16 " " - R_CURLY@16..17 "}" - SEMICOLON@17..18 ";" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs deleted file mode 100644 index 075f30159b24..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs +++ /dev/null @@ -1 +0,0 @@ -m1!{ let a = 0; }; diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast deleted file mode 100644 index 81d6df29a5fb..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast +++ /dev/null @@ -1,21 +0,0 @@ -EXPR_STMT@0..18 - MACRO_CALL@0..17 - PATH@0..2 - PATH_SEGMENT@0..2 - NAME_REF@0..2 - IDENT@0..2 "m1" - BANG@2..3 "!" - TOKEN_TREE@3..17 - L_CURLY@3..4 "{" - WHITESPACE@4..5 " " - LET_KW@5..8 "let" - WHITESPACE@8..9 " " - IDENT@9..10 "a" - WHITESPACE@10..11 " " - EQ@11..12 "=" - WHITESPACE@12..13 " " - INT_NUMBER@13..14 "0" - SEMICOLON@14..15 ";" - WHITESPACE@15..16 " " - R_CURLY@16..17 "}" - SEMICOLON@17..18 ";" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs deleted file mode 100644 index 075f30159b24..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs +++ /dev/null @@ -1 +0,0 @@ -m1!{ let a = 0; }; diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast deleted file mode 100644 index 64c5d296911e..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast +++ /dev/null @@ -1,22 +0,0 @@ -STRUCT@0..28 - STRUCT_KW@0..6 "struct" - WHITESPACE@6..7 " " - NAME@7..10 - IDENT@7..10 "Foo" - WHITESPACE@10..11 " " - RECORD_FIELD_LIST@11..28 - L_CURLY@11..12 "{" - WHITESPACE@12..17 "\n " - RECORD_FIELD@17..25 - NAME@17..20 - IDENT@17..20 "bar" - COLON@20..21 ":" - WHITESPACE@21..22 " " - PATH_TYPE@22..25 - PATH@22..25 - PATH_SEGMENT@22..25 - NAME_REF@22..25 - IDENT@22..25 "u32" - COMMA@25..26 "," - WHITESPACE@26..27 "\n" - R_CURLY@27..28 "}" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs deleted file mode 100644 index e5473e3ac8d7..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs +++ /dev/null @@ -1,3 +0,0 @@ -struct Foo { - bar: u32, -} diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast deleted file mode 100644 index 9089906bcea1..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast +++ /dev/null @@ -1,10 +0,0 @@ -EXPR_STMT@0..5 - CALL_EXPR@0..5 - PATH_EXPR@0..3 - PATH@0..3 - PATH_SEGMENT@0..3 - NAME_REF@0..3 - IDENT@0..3 "foo" - ARG_LIST@3..5 - L_PAREN@3..4 "(" - R_PAREN@4..5 ")" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs deleted file mode 100644 index eb28ef4401b2..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs +++ /dev/null @@ -1 +0,0 @@ -foo() diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast deleted file mode 100644 index 37663671fafb..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast +++ /dev/null @@ -1,11 +0,0 @@ -LET_STMT@0..10 - LET_KW@0..3 "let" - WHITESPACE@3..4 " " - IDENT_PAT@4..5 - NAME@4..5 - IDENT@4..5 "x" - WHITESPACE@5..6 " " - EQ@6..7 "=" - WHITESPACE@7..8 " " - LITERAL@8..10 - INT_NUMBER@8..10 "10" diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs deleted file mode 100644 index 78364b2a96e4..000000000000 --- a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs +++ /dev/null @@ -1 +0,0 @@ -let x = 10 diff --git a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast deleted file mode 100644 index 5df7507e2de1..000000000000 --- a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast +++ /dev/null @@ -1 +0,0 @@ -ERROR diff --git a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs b/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs deleted file mode 100644 index caa4d7c09275..000000000000 --- a/crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs +++ /dev/null @@ -1 +0,0 @@ -Result" diff --git a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs deleted file mode 100644 index b50b3bb3bfd6..000000000000 --- a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs +++ /dev/null @@ -1 +0,0 @@ -Result