internal: start isolating ssr-related parsing APIs to SSR
This commit is contained in:
parent
634c7682c9
commit
b468bd6645
21
crates/ide_ssr/src/fragments.rs
Normal file
21
crates/ide_ssr/src/fragments.rs
Normal file
@ -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())
|
||||
}
|
@ -71,6 +71,7 @@ mod from_comment;
|
||||
mod matching;
|
||||
mod nester;
|
||||
mod parsing;
|
||||
mod fragments;
|
||||
mod replacing;
|
||||
mod resolving;
|
||||
mod search;
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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, ()> {
|
||||
|
@ -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(
|
||||
|
@ -1 +0,0 @@
|
||||
ERROR
|
@ -1 +0,0 @@
|
||||
Result<Foo, Bar
|
@ -1,22 +0,0 @@
|
||||
PATH_TYPE@0..16
|
||||
PATH@0..16
|
||||
PATH_SEGMENT@0..16
|
||||
NAME_REF@0..6
|
||||
IDENT@0..6 "Result"
|
||||
GENERIC_ARG_LIST@6..16
|
||||
L_ANGLE@6..7 "<"
|
||||
TYPE_ARG@7..10
|
||||
PATH_TYPE@7..10
|
||||
PATH@7..10
|
||||
PATH_SEGMENT@7..10
|
||||
NAME_REF@7..10
|
||||
IDENT@7..10 "Foo"
|
||||
COMMA@10..11 ","
|
||||
WHITESPACE@11..12 " "
|
||||
TYPE_ARG@12..15
|
||||
PATH_TYPE@12..15
|
||||
PATH@12..15
|
||||
PATH_SEGMENT@12..15
|
||||
NAME_REF@12..15
|
||||
IDENT@12..15 "Bar"
|
||||
R_ANGLE@15..16 ">"
|
@ -1 +0,0 @@
|
||||
Result<Foo, Bar>
|
Loading…
x
Reference in New Issue
Block a user