From b468bd664539ece8db6ac63d3d652ec0679edd9e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 27 Dec 2021 19:44:45 +0300 Subject: [PATCH] internal: start isolating ssr-related parsing APIs to SSR --- crates/ide_ssr/src/fragments.rs | 21 ++++++++++++++++ crates/ide_ssr/src/lib.rs | 1 + crates/ide_ssr/src/parsing.rs | 24 +++++++++++++++++-- crates/parser/src/lib.rs | 2 -- crates/syntax/src/lib.rs | 7 ------ crates/syntax/src/tests.rs | 9 ------- .../type/err/0000_missing_close.rast | 1 - .../fragments/type/err/0000_missing_close.rs | 1 - .../parser/fragments/type/ok/0000_result.rast | 22 ----------------- .../parser/fragments/type/ok/0000_result.rs | 1 - 10 files changed, 44 insertions(+), 45 deletions(-) create mode 100644 crates/ide_ssr/src/fragments.rs delete mode 100644 crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast delete mode 100644 crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs delete mode 100644 crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast delete mode 100644 crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs diff --git a/crates/ide_ssr/src/fragments.rs b/crates/ide_ssr/src/fragments.rs new file mode 100644 index 0000000000..0abf9e4d98 --- /dev/null +++ b/crates/ide_ssr/src/fragments.rs @@ -0,0 +1,21 @@ +//! 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 parser::SyntaxKind; +use syntax::{ast, AstNode, SyntaxNode}; + +pub(crate) fn ty(s: &str) -> Result { + let template = "type T = {};"; + 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(ast::Type::cast).ok_or(())?; + Ok(node.syntax().clone()) +} diff --git a/crates/ide_ssr/src/lib.rs b/crates/ide_ssr/src/lib.rs index 2fe1f5b616..d56bc12b68 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 ae7d5b4bf1..b32efe879a 100644 --- a/crates/ide_ssr/src/parsing.rs +++ b/crates/ide_ssr/src/parsing.rs @@ -6,7 +6,7 @@ //! e.g. expressions, type references etc. use crate::errors::bail; -use crate::{SsrError, SsrPattern, SsrRule}; +use crate::{fragments, SsrError, SsrPattern, SsrRule}; use rustc_hash::{FxHashMap, FxHashSet}; use std::{fmt::Display, str::FromStr}; use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T}; @@ -79,7 +79,7 @@ impl ParsedRule { } else { builder.try_add(ast::Expr::parse(&raw_pattern), raw_template_stmt.clone()); } - builder.try_add(ast::Type::parse(&raw_pattern), raw_template.map(ast::Type::parse)); + builder.try_add2(fragments::ty(&raw_pattern), raw_template.map(fragments::ty)); 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)); @@ -114,6 +114,26 @@ impl RuleBuilder { } } + fn try_add2( + &mut self, + 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, + template: Some(template), + }), + (Ok(pattern), None) => self.rules.push(ParsedRule { + placeholders_by_stand_in: self.placeholders_by_stand_in.clone(), + pattern, + template: None, + }), + _ => {} + } + } + fn build(mut self) -> Result, SsrError> { if self.rules.is_empty() { bail!("Not a valid Rust expression, type, item, path or pattern"); diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 6827cf8bf1..fb5280d197 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -141,7 +141,6 @@ pub enum ParserEntryPoint { Path, Expr, StatementOptionalSemi, - Type, Pattern, Item, Attr, @@ -164,7 +163,6 @@ pub fn parse(inp: &Input, entry_point: ParserEntryPoint) -> Output { let entry_point: fn(&'_ mut parser::Parser) = match entry_point { ParserEntryPoint::Path => grammar::entry::prefix::path, ParserEntryPoint::Expr => grammar::entry::prefix::expr, - ParserEntryPoint::Type => grammar::entry::prefix::ty, ParserEntryPoint::Pattern => grammar::entry::prefix::pat, ParserEntryPoint::Item => grammar::entry::prefix::item, ParserEntryPoint::StatementOptionalSemi => grammar::entry_points::stmt_optional_semi, diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs index 65a6b7ac4e..b82df66162 100644 --- a/crates/syntax/src/lib.rs +++ b/crates/syntax/src/lib.rs @@ -201,13 +201,6 @@ impl ast::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 { diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 04105dedc9..a632d0e630 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs @@ -95,15 +95,6 @@ fn item_parser_tests() { ); } -#[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( 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 5df7507e2d..0000000000 --- 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 caa4d7c092..0000000000 --- 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 b50b3bb3bf..0000000000 --- a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs +++ /dev/null @@ -1 +0,0 @@ -Result