internal: start isolating ssr-related parsing APIs to SSR

This commit is contained in:
Aleksey Kladov 2021-12-27 19:44:45 +03:00
parent 634c7682c9
commit b468bd6645
10 changed files with 44 additions and 45 deletions

View 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())
}

View File

@ -71,6 +71,7 @@ mod from_comment;
mod matching;
mod nester;
mod parsing;
mod fragments;
mod replacing;
mod resolving;
mod search;

View File

@ -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");

View File

@ -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,

View File

@ -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, ()> {

View File

@ -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(

View File

@ -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 ">"

View File

@ -1 +0,0 @@
Result<Foo, Bar>