From 69689625ce4465f2d008d6543553d0d91d53dca4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 14:35:26 +0300 Subject: move ast builder to a separate file --- .../src/assists/add_missing_impl_members.rs | 5 +- crates/ra_assists/src/assists/fill_match_arms.rs | 2 +- crates/ra_assists/src/assists/move_bounds.rs | 2 +- crates/ra_assists/src/ast_builder.rs | 229 ++++++++++++++++++++ crates/ra_assists/src/ast_editor.rs | 231 +-------------------- crates/ra_assists/src/lib.rs | 1 + 6 files changed, 236 insertions(+), 234 deletions(-) create mode 100644 crates/ra_assists/src/ast_builder.rs (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index cbeb7054f..2894bdd8a 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs @@ -4,10 +4,7 @@ use ra_syntax::{ SmolStr, }; -use crate::{ - ast_editor::{AstBuilder, AstEditor}, - Assist, AssistCtx, AssistId, -}; +use crate::{ast_builder::AstBuilder, ast_editor::AstEditor, Assist, AssistCtx, AssistId}; #[derive(PartialEq)] enum AddMissingImplMembersMode { diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs index f59062bb9..771aa625f 100644 --- a/crates/ra_assists/src/assists/fill_match_arms.rs +++ b/crates/ra_assists/src/assists/fill_match_arms.rs @@ -3,7 +3,7 @@ use std::iter; use hir::{db::HirDatabase, Adt, HasSource}; use ra_syntax::ast::{self, AstNode, NameOwner}; -use crate::{ast_editor::AstBuilder, Assist, AssistCtx, AssistId}; +use crate::{ast_builder::AstBuilder, Assist, AssistCtx, AssistId}; pub(crate) fn fill_match_arms(mut ctx: AssistCtx) -> Option { let match_expr = ctx.node_at_offset::()?; diff --git a/crates/ra_assists/src/assists/move_bounds.rs b/crates/ra_assists/src/assists/move_bounds.rs index 526de1d98..aa9036fed 100644 --- a/crates/ra_assists/src/assists/move_bounds.rs +++ b/crates/ra_assists/src/assists/move_bounds.rs @@ -6,7 +6,7 @@ use ra_syntax::{ TextRange, }; -use crate::{ast_editor::AstBuilder, Assist, AssistCtx, AssistId}; +use crate::{ast_builder::AstBuilder, Assist, AssistCtx, AssistId}; pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx) -> Option { let type_param_list = ctx.node_at_offset::()?; diff --git a/crates/ra_assists/src/ast_builder.rs b/crates/ra_assists/src/ast_builder.rs new file mode 100644 index 000000000..e4ea1fca9 --- /dev/null +++ b/crates/ra_assists/src/ast_builder.rs @@ -0,0 +1,229 @@ +use itertools::Itertools; + +use hir::Name; +use ra_syntax::{ast, AstNode, SourceFile}; + +pub struct AstBuilder { + _phantom: std::marker::PhantomData, +} + +impl AstBuilder { + pub fn from_name(name: &Name) -> ast::RecordField { + ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name)) + } + + fn from_text(text: &str) -> ast::RecordField { + ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text)) + } + + pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::RecordField { + match expr { + Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())), + None => Self::from_text(&name.syntax().to_string()), + } + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::Block { + ast_node_from_file_text(&format!("fn f() {}", text)) + } + + pub fn single_expr(e: &ast::Expr) -> ast::Block { + Self::from_text(&format!("{{ {} }}", e.syntax())) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::Expr { + ast_node_from_file_text(&format!("const C: () = {};", text)) + } + + pub fn unit() -> ast::Expr { + Self::from_text("()") + } + + pub fn unimplemented() -> ast::Expr { + Self::from_text("unimplemented!()") + } +} + +impl AstBuilder { + pub fn new(text: &str) -> ast::NameRef { + ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::Path { + ast_node_from_file_text(text) + } + + pub fn from_name(name: ast::Name) -> ast::Path { + let name = name.syntax().to_string(); + Self::from_text(name.as_str()) + } + + pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path { + Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax())) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::BindPat { + ast_node_from_file_text(&format!("fn f({}: ())", text)) + } + + pub fn from_name(name: &ast::Name) -> ast::BindPat { + Self::from_text(name.text()) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::PlaceholderPat { + ast_node_from_file_text(&format!("fn f({}: ())", text)) + } + + pub fn placeholder() -> ast::PlaceholderPat { + Self::from_text("_") + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::TupleStructPat { + ast_node_from_file_text(&format!("fn f({}: ())", text)) + } + + pub fn from_pieces( + path: &ast::Path, + pats: impl Iterator, + ) -> ast::TupleStructPat { + let pats_str = pats.map(|p| p.syntax().to_string()).collect::>().join(", "); + Self::from_text(&format!("{}({})", path.syntax(), pats_str)) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::RecordPat { + ast_node_from_file_text(&format!("fn f({}: ())", text)) + } + + pub fn from_pieces(path: &ast::Path, pats: impl Iterator) -> ast::RecordPat { + let pats_str = pats.map(|p| p.syntax().to_string()).collect::>().join(", "); + Self::from_text(&format!("{}{{ {} }}", path.syntax(), pats_str)) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::PathPat { + ast_node_from_file_text(&format!("fn f({}: ())", text)) + } + + pub fn from_path(path: &ast::Path) -> ast::PathPat { + let path_str = path.syntax().text().to_string(); + Self::from_text(path_str.as_str()) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::MatchArm { + ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) + } + + pub fn from_pieces(pats: impl Iterator, expr: &ast::Expr) -> ast::MatchArm { + let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); + Self::from_text(&format!("{} => {}", pats_str, expr.syntax())) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::MatchArmList { + ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) + } + + pub fn from_arms(arms: impl Iterator) -> ast::MatchArmList { + let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); + Self::from_text(&format!("{},\n", arms_str)) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::WherePred { + ast_node_from_file_text(&format!("fn f() where {} {{ }}", text)) + } + + pub fn from_pieces( + path: ast::Path, + bounds: impl Iterator, + ) -> ast::WherePred { + let bounds = bounds.map(|b| b.syntax().to_string()).collect::>().join(" + "); + Self::from_text(&format!("{}: {}", path.syntax(), bounds)) + } +} + +impl AstBuilder { + fn from_text(text: &str) -> ast::WhereClause { + ast_node_from_file_text(&format!("fn f() where {} {{ }}", text)) + } + + pub fn from_predicates(preds: impl Iterator) -> ast::WhereClause { + let preds = preds.map(|p| p.syntax().to_string()).collect::>().join(", "); + Self::from_text(preds.as_str()) + } +} + +fn ast_node_from_file_text(text: &str) -> N { + let parse = SourceFile::parse(text); + let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); + res +} + +pub(crate) mod tokens { + use once_cell::sync::Lazy; + use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; + + static SOURCE_FILE: Lazy> = Lazy::new(|| SourceFile::parse(",\n; ;")); + + pub(crate) fn comma() -> SyntaxToken { + SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == T![,]) + .unwrap() + } + + pub(crate) fn single_space() -> SyntaxToken { + SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") + .unwrap() + } + + #[allow(unused)] + pub(crate) fn single_newline() -> SyntaxToken { + SOURCE_FILE + .tree() + .syntax() + .descendants_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") + .unwrap() + } + + pub(crate) struct WsBuilder(SourceFile); + + impl WsBuilder { + pub(crate) fn new(text: &str) -> WsBuilder { + WsBuilder(SourceFile::parse(text).ok().unwrap()) + } + pub(crate) fn ws(&self) -> SyntaxToken { + self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() + } + } + +} diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs index a710edce8..81621afef 100644 --- a/crates/ra_assists/src/ast_editor.rs +++ b/crates/ra_assists/src/ast_editor.rs @@ -1,18 +1,18 @@ use std::{iter, ops::RangeInclusive}; use arrayvec::ArrayVec; -use itertools::Itertools; -use hir::Name; use ra_fmt::leading_indent; use ra_syntax::{ algo::{insert_children, replace_children}, - ast, AstNode, Direction, InsertPosition, SourceFile, SyntaxElement, + ast, AstNode, Direction, InsertPosition, SyntaxElement, SyntaxKind::*, T, }; use ra_text_edit::TextEditBuilder; +use crate::ast_builder::tokens; + pub struct AstEditor { original_ast: N, ast: N, @@ -240,228 +240,3 @@ impl AstEditor { self.ast = self.replace_children(replace_range, to_insert.into_iter()) } } - -pub struct AstBuilder { - _phantom: std::marker::PhantomData, -} - -impl AstBuilder { - pub fn from_name(name: &Name) -> ast::RecordField { - ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name)) - } - - fn from_text(text: &str) -> ast::RecordField { - ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text)) - } - - pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::RecordField { - match expr { - Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())), - None => Self::from_text(&name.syntax().to_string()), - } - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::Block { - ast_node_from_file_text(&format!("fn f() {}", text)) - } - - pub fn single_expr(e: &ast::Expr) -> ast::Block { - Self::from_text(&format!("{{ {} }}", e.syntax())) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::Expr { - ast_node_from_file_text(&format!("const C: () = {};", text)) - } - - pub fn unit() -> ast::Expr { - Self::from_text("()") - } - - pub fn unimplemented() -> ast::Expr { - Self::from_text("unimplemented!()") - } -} - -impl AstBuilder { - pub fn new(text: &str) -> ast::NameRef { - ast_node_from_file_text(&format!("fn f() {{ {}; }}", text)) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::Path { - ast_node_from_file_text(text) - } - - pub fn from_name(name: ast::Name) -> ast::Path { - let name = name.syntax().to_string(); - Self::from_text(name.as_str()) - } - - pub fn from_pieces(enum_name: ast::Name, var_name: ast::Name) -> ast::Path { - Self::from_text(&format!("{}::{}", enum_name.syntax(), var_name.syntax())) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::BindPat { - ast_node_from_file_text(&format!("fn f({}: ())", text)) - } - - pub fn from_name(name: &ast::Name) -> ast::BindPat { - Self::from_text(name.text()) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::PlaceholderPat { - ast_node_from_file_text(&format!("fn f({}: ())", text)) - } - - pub fn placeholder() -> ast::PlaceholderPat { - Self::from_text("_") - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::TupleStructPat { - ast_node_from_file_text(&format!("fn f({}: ())", text)) - } - - pub fn from_pieces( - path: &ast::Path, - pats: impl Iterator, - ) -> ast::TupleStructPat { - let pats_str = pats.map(|p| p.syntax().to_string()).collect::>().join(", "); - Self::from_text(&format!("{}({})", path.syntax(), pats_str)) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::RecordPat { - ast_node_from_file_text(&format!("fn f({}: ())", text)) - } - - pub fn from_pieces(path: &ast::Path, pats: impl Iterator) -> ast::RecordPat { - let pats_str = pats.map(|p| p.syntax().to_string()).collect::>().join(", "); - Self::from_text(&format!("{}{{ {} }}", path.syntax(), pats_str)) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::PathPat { - ast_node_from_file_text(&format!("fn f({}: ())", text)) - } - - pub fn from_path(path: &ast::Path) -> ast::PathPat { - let path_str = path.syntax().text().to_string(); - Self::from_text(path_str.as_str()) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::MatchArm { - ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) - } - - pub fn from_pieces(pats: impl Iterator, expr: &ast::Expr) -> ast::MatchArm { - let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); - Self::from_text(&format!("{} => {}", pats_str, expr.syntax())) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::MatchArmList { - ast_node_from_file_text(&format!("fn f() {{ match () {{{}}} }}", text)) - } - - pub fn from_arms(arms: impl Iterator) -> ast::MatchArmList { - let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); - Self::from_text(&format!("{},\n", arms_str)) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::WherePred { - ast_node_from_file_text(&format!("fn f() where {} {{ }}", text)) - } - - pub fn from_pieces( - path: ast::Path, - bounds: impl Iterator, - ) -> ast::WherePred { - let bounds = bounds.map(|b| b.syntax().to_string()).collect::>().join(" + "); - Self::from_text(&format!("{}: {}", path.syntax(), bounds)) - } -} - -impl AstBuilder { - fn from_text(text: &str) -> ast::WhereClause { - ast_node_from_file_text(&format!("fn f() where {} {{ }}", text)) - } - - pub fn from_predicates(preds: impl Iterator) -> ast::WhereClause { - let preds = preds.map(|p| p.syntax().to_string()).collect::>().join(", "); - Self::from_text(preds.as_str()) - } -} - -fn ast_node_from_file_text(text: &str) -> N { - let parse = SourceFile::parse(text); - let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); - res -} - -mod tokens { - use once_cell::sync::Lazy; - use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; - - static SOURCE_FILE: Lazy> = Lazy::new(|| SourceFile::parse(",\n; ;")); - - pub(crate) fn comma() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == T![,]) - .unwrap() - } - - pub(crate) fn single_space() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") - .unwrap() - } - - #[allow(unused)] - pub(crate) fn single_newline() -> SyntaxToken { - SOURCE_FILE - .tree() - .syntax() - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") - .unwrap() - } - - pub(crate) struct WsBuilder(SourceFile); - - impl WsBuilder { - pub(crate) fn new(text: &str) -> WsBuilder { - WsBuilder(SourceFile::parse(text).ok().unwrap()) - } - pub(crate) fn ws(&self) -> SyntaxToken { - self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() - } - } - -} diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 5e4e8bc92..71b017076 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -8,6 +8,7 @@ mod assist_ctx; mod marks; pub mod ast_editor; +pub mod ast_builder; use itertools::Itertools; -- cgit v1.2.3