Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/ide_ssr/src/fragments.rs21
-rw-r--r--crates/ide_ssr/src/lib.rs1
-rw-r--r--crates/ide_ssr/src/parsing.rs24
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/syntax/src/lib.rs7
-rw-r--r--crates/syntax/src/tests.rs9
-rw-r--r--crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/type/err/0000_missing_close.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast22
-rw-r--r--crates/syntax/test_data/parser/fragments/type/ok/0000_result.rs1
10 files changed, 44 insertions, 45 deletions
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<SyntaxNode, ()> {
+ 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<SyntaxNode, ()>,
+ template: Option<Result<SyntaxNode, ()>>,
+ ) {
+ 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<Vec<ParsedRule>, 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<Self, ()> {
- 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<Self, ()> {
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
@@ -96,15 +96,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(
&["parser/fragments/stmt/ok"],
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<Foo, Bar
diff --git a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast b/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast
deleted file mode 100644
index 38c15b5815..0000000000
--- a/crates/syntax/test_data/parser/fragments/type/ok/0000_result.rast
+++ /dev/null
@@ -1,22 +0,0 @@
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<Foo, Bar>