Repository: rust-analyzer/rust-analyzer
Pull request #8783 (2021-05-09 16:55:20)

internal: introduce `ast::make::ext` module with common shortcuts
bors r+
🤖


Patch:
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index cad8a7479a..8d13c7e047 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -18,7 +18,7 @@ use hir_expand::{
     ast_id_map::FileAstId,
     hygiene::Hygiene,
     name::{name, AsName, Name},
-    FragmentKind, HirFileId, InFile,
+    HirFileId, InFile,
 };
 use la_arena::{Arena, Idx, RawIdx};
 use profile::Count;
@@ -656,7 +656,6 @@ pub struct MacroCall {
     /// Path to the called macro.
     pub path: Interned<ModPath>,
     pub ast_id: FileAstId<ast::MacroCall>,
-    pub fragment: FragmentKind,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index fe348091d0..5743b33862 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -624,8 +624,7 @@ impl<'a> Ctx<'a> {
     fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
         let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
         let ast_id = self.source_ast_id_map.ast_id(m);
-        let fragment = hir_expand::to_fragment_kind(m);
-        let res = MacroCall { path, ast_id, fragment };
+        let res = MacroCall { path, ast_id };
         Some(id(self.data().macro_calls.alloc(res)))
     }
 
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index e96ca953ff..da46f16f7a 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -62,8 +62,7 @@ use hir_expand::{
     ast_id_map::FileAstId,
     eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
     hygiene::Hygiene,
-    AstId, AttrId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
-    MacroDefKind,
+    AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
 };
 use la_arena::Idx;
 use nameres::DefMap;
@@ -653,7 +652,6 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
         mut error_sink: &mut dyn FnMut(mbe::ExpandError),
     ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
-        let fragment = hir_expand::to_fragment_kind(self.value);
         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
         let h = Hygiene::new(db.upcast(), self.file_id);
         let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
@@ -669,7 +667,6 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
 
         macro_call_as_call_id(
             &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
-            fragment,
             db,
             krate,
             resolver,
@@ -698,7 +695,6 @@ pub struct UnresolvedMacro {
 
 fn macro_call_as_call_id(
     call: &AstIdWithPath<ast::MacroCall>,
-    fragment: FragmentKind,
     db: &dyn db::DefDatabase,
     krate: CrateId,
     resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -722,11 +718,7 @@ fn macro_call_as_call_id(
         .map(MacroCallId::from)
     } else {
         Ok(def
-            .as_lazy_macro(
-                db.upcast(),
-                krate,
-                MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
-            )
+            .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id })
             .into())
     };
     Ok(res)
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 249af6fc80..1bc72ec1f0 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -629,7 +629,7 @@ mod diagnostics {
                 DiagnosticKind::UnresolvedProcMacro { ast } => {
                     let mut precise_location = None;
                     let (file, ast, name) = match ast {
-                        MacroCallKind::FnLike { ast_id, .. } => {
+                        MacroCallKind::FnLike { ast_id } => {
                             let node = ast_id.to_node(db.upcast());
                             (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
                         }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index e89136ed1d..05ceb1efb6 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
     builtin_macro::find_builtin_macro,
     name::{AsName, Name},
     proc_macro::ProcMacroExpander,
-    AttrId, FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
+    AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
 };
 use hir_expand::{InFile, MacroCallLoc};
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -215,7 +215,7 @@ struct MacroDirective {
 
 #[derive(Clone, Debug, Eq, PartialEq)]
 enum MacroDirectiveKind {
-    FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
+    FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
     Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
 }
 
@@ -807,10 +807,9 @@ impl DefCollector<'_> {
         let mut res = ReachedFixedPoint::Yes;
         macros.retain(|directive| {
             match &directive.kind {
-                MacroDirectiveKind::FnLike { ast_id, fragment } => {
+                MacroDirectiveKind::FnLike { ast_id } => {
                     match macro_call_as_call_id(
                         ast_id,
-                        *fragment,
                         self.db,
                         self.def_map.krate,
                         |path| {
@@ -927,9 +926,8 @@ impl DefCollector<'_> {
 
         for directive in &self.unexpanded_macros {
             match &directive.kind {
-                MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
+                MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id(
                     ast_id,
-                    *fragment,
                     self.db,
                     self.def_map.krate,
                     |path| {
@@ -1498,7 +1496,6 @@ impl ModCollector<'_, '_> {
         let mut error = None;
         match macro_call_as_call_id(
             &ast_id,
-            mac.fragment,
             self.def_collector.db,
             self.def_collector.def_map.krate,
             |path| {
@@ -1527,14 +1524,9 @@ impl ModCollector<'_, '_> {
             }
             Ok(Err(_)) => {
                 // Built-in macro failed eager expansion.
-
-                // FIXME: don't parse the file here
-                let fragment = hir_expand::to_fragment_kind(
-                    &ast_id.ast_id.to_node(self.def_collector.db.upcast()),
-                );
                 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
                     self.module_id,
-                    MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
+                    MacroCallKind::FnLike { ast_id: ast_id.ast_id },
                     error.unwrap().to_string(),
                 ));
                 return;
@@ -1551,7 +1543,7 @@ impl ModCollector<'_, '_> {
         self.def_collector.unexpanded_macros.push(MacroDirective {
             module_id: self.module_id,
             depth: self.macro_depth + 1,
-            kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
+            kind: MacroDirectiveKind::FnLike { ast_id },
         });
     }
 
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index af98021441..0142a06ed8 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -578,7 +578,6 @@ mod tests {
                     krate,
                     kind: MacroCallKind::FnLike {
                         ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
-                        fragment: FragmentKind::Expr,
                     },
                 };
 
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 6647e57e7d..d61f4b31a4 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -8,7 +8,9 @@ use parser::FragmentKind;
 use syntax::{
     algo::diff,
     ast::{self, NameOwner},
-    AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken,
+    AstNode, GreenNode, Parse,
+    SyntaxKind::*,
+    SyntaxNode, SyntaxToken,
 };
 
 use crate::{
@@ -158,7 +160,7 @@ pub fn expand_hypothetical(
 
     let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt);
 
-    let fragment_kind = macro_fragment_kind(db, actual_macro_call);
+    let fragment_kind = to_fragment_kind(db, actual_macro_call);
 
     let (node, tmap_2) =
         mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?;
@@ -224,7 +226,7 @@ fn parse_macro_expansion(
         None => return ExpandResult { value: None, err: result.err },
     };
 
-    let fragment_kind = macro_fragment_kind(db, macro_file.macro_call_id);
+    let fragment_kind = to_fragment_kind(db, macro_file.macro_call_id);
 
     log::debug!("expanded = {}", tt.as_debug_string());
     log::debug!("kind = {:?}", fragment_kind);
@@ -425,15 +427,62 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
     Arc::new(HygieneFrame::new(db, file_id))
 }
 
-fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
-    match id {
-        MacroCallId::LazyMacro(id) => {
-            let loc: MacroCallLoc = db.lookup_intern_macro(id);
-            loc.kind.fragment_kind()
-        }
+/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
+/// FIXME: Not completed
+fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
+    let lazy_id = match id {
+        MacroCallId::LazyMacro(id) => id,
         MacroCallId::EagerMacro(id) => {
-            let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
-            loc.fragment
+            return db.lookup_intern_eager_expansion(id).fragment;
+        }
+    };
+    let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value;
+
+    let parent = match syn.parent() {
+        Some(it) => it,
+        None => return FragmentKind::Statements,
+    };
+
+    match parent.kind() {
+        MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
+        MACRO_STMTS => FragmentKind::Statements,
+        MACRO_PAT => FragmentKind::Pattern,
+        MACRO_TYPE => FragmentKind::Type,
+        ITEM_LIST => FragmentKind::Items,
+        LET_STMT => {
+            // FIXME: Handle LHS Pattern
+            FragmentKind::Expr
+        }
+        EXPR_STMT => FragmentKind::Statements,
+        BLOCK_EXPR => FragmentKind::Statements,
+        ARG_LIST => FragmentKind::Expr,
+        TRY_EXPR => FragmentKind::Expr,
+        TUPLE_EXPR => FragmentKind::Expr,
+        PAREN_EXPR => FragmentKind::Expr,
+        ARRAY_EXPR => FragmentKind::Expr,
+        FOR_EXPR => FragmentKind::Expr,
+        PATH_EXPR => FragmentKind::Expr,
+        CLOSURE_EXPR => FragmentKind::Expr,
+        CONDITION => FragmentKind::Expr,
+        BREAK_EXPR => FragmentKind::Expr,
+        RETURN_EXPR => FragmentKind::Expr,
+        MATCH_EXPR => FragmentKind::Expr,
+        MATCH_ARM => FragmentKind::Expr,
+        MATCH_GUARD => FragmentKind::Expr,
+        RECORD_EXPR_FIELD => FragmentKind::Expr,
+        CALL_EXPR => FragmentKind::Expr,
+        INDEX_EXPR => FragmentKind::Expr,
+        METHOD_CALL_EXPR => FragmentKind::Expr,
+        FIELD_EXPR => FragmentKind::Expr,
+        AWAIT_EXPR => FragmentKind::Expr,
+        CAST_EXPR => FragmentKind::Expr,
+        REF_EXPR => FragmentKind::Expr,
+        PREFIX_EXPR => FragmentKind::Expr,
+        RANGE_EXPR => FragmentKind::Expr,
+        BIN_EXPR => FragmentKind::Expr,
+        _ => {
+            // Unknown , Just guess it is `Items`
+            FragmentKind::Items
         }
     }
 }
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 85491fe8be..f12132f84b 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -175,13 +175,8 @@ fn lazy_expand(
 ) -> ExpandResult<Option<InFile<SyntaxNode>>> {
     let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
 
-    let fragment = crate::to_fragment_kind(&macro_call.value);
     let id: MacroCallId = def
-        .as_lazy_macro(
-            db,
-            krate,
-            MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment },
-        )
+        .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) })
         .into();
 
     let err = db.macro_expand_error(id);
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 80ab3aeee7..0402640de3 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -16,9 +16,7 @@ pub mod quote;
 pub mod eager;
 
 use either::Either;
-
 pub use mbe::{ExpandError, ExpandResult};
-pub use parser::FragmentKind;
 
 use std::hash::Hash;
 use std::sync::Arc;
@@ -292,7 +290,7 @@ pub struct MacroCallLoc {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum MacroCallKind {
-    FnLike { ast_id: AstId<ast::MacroCall>, fragment: FragmentKind },
+    FnLike { ast_id: AstId<ast::MacroCall> },
     Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId },
 }
 
@@ -326,13 +324,6 @@ impl MacroCallKind {
             MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
         }
     }
-
-    fn fragment_kind(&self) -> FragmentKind {
-        match self {
-            MacroCallKind::FnLike { fragment, .. } => *fragment,
-            MacroCallKind::Derive { .. } => FragmentKind::Items,
-        }
-    }
 }
 
 impl MacroCallId {
@@ -366,6 +357,7 @@ pub struct ExpansionInfo {
 }
 
 pub use mbe::Origin;
+use parser::FragmentKind;
 
 impl ExpansionInfo {
     pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
@@ -570,59 +562,3 @@ impl<N: AstNode> InFile<N> {
         self.with_value(self.value.syntax())
     }
 }
-
-/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
-/// FIXME: Not completed
-pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind {
-    use syntax::SyntaxKind::*;
-
-    let syn = call.syntax();
-
-    let parent = match syn.parent() {
-        Some(it) => it,
-        None => return FragmentKind::Statements,
-    };
-
-    match parent.kind() {
-        MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
-        MACRO_STMTS => FragmentKind::Statements,
-        MACRO_PAT => FragmentKind::Pattern,
-        MACRO_TYPE => FragmentKind::Type,
-        ITEM_LIST => FragmentKind::Items,
-        LET_STMT => {
-            // FIXME: Handle LHS Pattern
-            FragmentKind::Expr
-        }
-        EXPR_STMT => FragmentKind::Statements,
-        BLOCK_EXPR => FragmentKind::Statements,
-        ARG_LIST => FragmentKind::Expr,
-        TRY_EXPR => FragmentKind::Expr,
-        TUPLE_EXPR => FragmentKind::Expr,
-        PAREN_EXPR => FragmentKind::Expr,
-        ARRAY_EXPR => FragmentKind::Expr,
-        FOR_EXPR => FragmentKind::Expr,
-        PATH_EXPR => FragmentKind::Expr,
-        CLOSURE_EXPR => FragmentKind::Expr,
-        CONDITION => FragmentKind::Expr,
-        BREAK_EXPR => FragmentKind::Expr,
-        RETURN_EXPR => FragmentKind::Expr,
-        MATCH_EXPR => FragmentKind::Expr,
-        MATCH_ARM => FragmentKind::Expr,
-        MATCH_GUARD => FragmentKind::Expr,
-        RECORD_EXPR_FIELD => FragmentKind::Expr,
-        CALL_EXPR => FragmentKind::Expr,
-        INDEX_EXPR => FragmentKind::Expr,
-        METHOD_CALL_EXPR => FragmentKind::Expr,
-        FIELD_EXPR => FragmentKind::Expr,
-        AWAIT_EXPR => FragmentKind::Expr,
-        CAST_EXPR => FragmentKind::Expr,
-        REF_EXPR => FragmentKind::Expr,
-        PREFIX_EXPR => FragmentKind::Expr,
-        RANGE_EXPR => FragmentKind::Expr,
-        BIN_EXPR => FragmentKind::Expr,
-        _ => {
-            // Unknown , Just guess it is `Items`
-            FragmentKind::Items
-        }
-    }
-}
diff --git a/crates/ide_assists/src/handlers/early_return.rs b/crates/ide_assists/src/handlers/early_return.rs
index c66f8c05d3..5eb6a57f07 100644
--- a/crates/ide_assists/src/handlers/early_return.rs
+++ b/crates/ide_assists/src/handlers/early_return.rs
@@ -130,9 +130,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
                                 once(make::ident_pat(make::name("it")).into()),
                             );
                             let expr = {
-                                let name_ref = make::name_ref("it");
-                                let segment = make::path_segment(name_ref);
-                                let path = make::path_unqualified(segment);
+                                let path = make::ext::ident_path("it");
                                 make::expr_path(path)
                             };
                             make::match_arm(once(pat.into()), expr)
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index e3095f26b5..da8d245e5f 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -65,8 +65,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
 
             let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
             let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
-                let path =
-                    make::path_unqualified(make::path_segment(make::name_ref(&n.to_string())));
+                let path = make::ext::ident_path(&n.to_string());
                 make::use_tree(path, None, None, false)
             }))
             .clone_for_update();
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 494ef4621e..6311afc1f5 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -956,10 +956,10 @@ fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel)
     let args = fun.params.iter().map(|param| param.to_arg(ctx));
     let args = make::arg_list(args);
     let call_expr = if fun.self_param.is_some() {
-        let self_arg = make::expr_path(make_path_from_text("self"));
+        let self_arg = make::expr_path(make::ext::ident_path("self"));
         make::expr_method_call(self_arg, &fun.name, args)
     } else {
-        let func = make::expr_path(make_path_from_text(&fun.name));
+        let func = make::expr_path(make::ext::ident_path(&fun.name));
         make::expr_call(func, args)
     };
 
@@ -1054,11 +1054,11 @@ impl FlowHandler {
                 make::expr_if(condition, block, None)
             }
             FlowHandler::IfOption { action } => {
-                let path = make_path_from_text("Some");
+                let path = make::ext::ident_path("Some");
                 let value_pat = make::ident_pat(make::name("value"));
                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
                 let cond = make::condition(call_expr, Some(pattern.into()));
-                let value = make::expr_path(make_path_from_text("value"));
+                let value = make::expr_path(make::ext::ident_path("value"));
                 let action_expr = action.make_result_handler(Some(value));
                 let action_stmt = make::expr_stmt(action_expr);
                 let then = make::block_expr(iter::once(action_stmt.into()), None);
@@ -1068,14 +1068,14 @@ impl FlowHandler {
                 let some_name = "value";
 
                 let some_arm = {
-                    let path = make_path_from_text("Some");
+                    let path = make::ext::ident_path("Some");
                     let value_pat = make::ident_pat(make::name(some_name));
                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
-                    let value = make::expr_path(make_path_from_text(some_name));
+                    let value = make::expr_path(make::ext::ident_path(some_name));
                     make::match_arm(iter::once(pat.into()), value)
                 };
                 let none_arm = {
-                    let path = make_path_from_text("None");
+                    let path = make::ext::ident_path("None");
                     let pat = make::path_pat(path);
                     make::match_arm(iter::once(pat), none.make_result_handler(None))
                 };
@@ -1087,17 +1087,17 @@ impl FlowHandler {
                 let err_name = "value";
 
                 let ok_arm = {
-                    let path = make_path_from_text("Ok");
+                    let path = make::ext::ident_path("Ok");
                     let value_pat = make::ident_pat(make::name(ok_name));
                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
-                    let value = make::expr_path(make_path_from_text(ok_name));
+                    let value = make::expr_path(make::ext::ident_path(ok_name));
                     make::match_arm(iter::once(pat.into()), value)
                 };
                 let err_arm = {
-                    let path = make_path_from_text("Err");
+                    let path = make::ext::ident_path("Err");
                     let value_pat = make::ident_pat(make::name(err_name));
                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
-                    let value = make::expr_path(make_path_from_text(err_name));
+                    let value = make::expr_path(make::ext::ident_path(err_name));
                     make::match_arm(iter::once(pat.into()), err.make_result_handler(Some(value)))
                 };
                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
@@ -1107,13 +1107,9 @@ impl FlowHandler {
     }
 }
 
-fn make_path_from_text(text: &str) -> ast::Path {
-    make::path_unqualified(make::path_segment(make::name_ref(text)))
-}
-
 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
     let name = var.name(ctx.db()).unwrap().to_string();
-    make::expr_path(make_path_from_text(&name))
+    make::expr_path(make::ext::ident_path(&name))
 }
 
 fn format_function(
@@ -1179,7 +1175,7 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti
             fun_ty.make_ty(ctx, module)
         }
         FlowHandler::Try { kind: TryKind::Option } => {
-            make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module)))
+            make::ext::ty_option(fun_ty.make_ty(ctx, module))
         }
         FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
             let handler_ty = parent_ret_ty
@@ -1187,29 +1183,21 @@ fn make_ret_ty(ctx: &AssistContext, module: hir::Module, fun: &Function) -> Opti
                 .nth(1)
                 .map(|ty| make_ty(&ty, ctx, module))
                 .unwrap_or_else(make::ty_unit);
-            make::ty_generic(
-                make::name_ref("Result"),
-                vec![fun_ty.make_ty(ctx, module), handler_ty],
-            )
+            make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
         }
-        FlowHandler::If { .. } => make::ty_bool(),
+        FlowHandler::If { .. } => make::ext::ty_bool(),
         FlowHandler::IfOption { action } => {
             let handler_ty = action
                 .expr_ty(ctx)
                 .map(|ty| make_ty(&ty, ctx, module))
                 .unwrap_or_else(make::ty_unit);
-            make::ty_generic(make::name_ref("Option"), iter::once(handler_ty))
-        }
-        FlowHandler::MatchOption { .. } => {
-            make::ty_generic(make::name_ref("Option"), iter::once(fun_ty.make_ty(ctx, module)))
+            make::ext::ty_option(handler_ty)
         }
+        FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
         FlowHandler::MatchResult { err } => {
             let handler_ty =
                 err.expr_ty(ctx).map(|ty| make_ty(&ty, ctx, module)).unwrap_or_else(make::ty_unit);
-            make::ty_generic(
-                make::name_ref("Result"),
-                vec![fun_ty.make_ty(ctx, module), handler_ty],
-            )
+            make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
         }
     };
     Some(make::ret_type(ret_ty))
@@ -1296,7 +1284,7 @@ fn make_body(
                     TryKind::Option => "Some",
                     TryKind::Result { .. } => "Ok",
                 };
-                let func = make::expr_path(make_path_from_text(constructor));
+                let func = make::expr_path(make::ext::ident_path(constructor));
                 let args = make::arg_list(iter::once(tail_expr));
                 make::expr_call(func, args)
             })
@@ -1306,16 +1294,16 @@ fn make_body(
             with_tail_expr(block, lit_false.into())
         }
         FlowHandler::IfOption { .. } => {
-            let none = make::expr_path(make_path_from_text("None"));
+            let none = make::expr_path(make::ext::ident_path("None"));
             with_tail_expr(block, none)
         }
         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
-            let some = make::expr_path(make_path_from_text("Some"));
+            let some = make::expr_path(make::ext::ident_path("Some"));
             let args = make::arg_list(iter::once(tail_expr));
             make::expr_call(some, args)
         }),
         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
-            let ok = make::expr_path(make_path_from_text("Ok"));
+            let ok = make::expr_path(make::ext::ident_path("Ok"));
             let args = make::arg_list(iter::once(tail_expr));
             make::expr_call(ok, args)
         }),
@@ -1483,13 +1471,13 @@ fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Op
         FlowHandler::IfOption { .. } => {
             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
             let args = make::arg_list(iter::once(expr));
-            make::expr_call(make::expr_path(make_path_from_text("Some")), args)
+            make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
         }
-        FlowHandler::MatchOption { .. } => make::expr_path(make_path_from_text("None")),
+        FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
         FlowHandler::MatchResult { .. } => {
             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
             let args = make::arg_list(iter::once(expr));
-            make::expr_call(make::expr_path(make_path_from_text("Err")), args)
+            make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
         }
     };
     Some(make::expr_return(Some(value)).clone_for_update())
diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 6f95b1a073..bc9fc524b9 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -175,7 +175,7 @@ impl FunctionBuilder {
     }
 
     fn render(self) -> FunctionTemplate {
-        let placeholder_expr = make::expr_todo();
+        let placeholder_expr = make::ext::expr_todo();
         let fn_body = make::block_expr(vec![], Some(placeholder_expr));
         let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
         let mut fn_def = make::fn_(
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs
index 011a28d446..fa3f766093 100644
--- a/crates/ide_assists/src/handlers/move_bounds.rs
+++ b/crates/ide_assists/src/handlers/move_bounds.rs
@@ -63,11 +63,7 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
 }
 
 fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
-    let path = {
-        let name_ref = make::name_ref(&param.name()?.syntax().to_string());
-        let segment = make::path_segment(name_ref);
-        make::path_unqualified(segment)
-    };
+    let path = make::ext::ident_path(&param.name()?.syntax().to_string());
     let predicate = make::where_pred(path, param.type_bound_list()?.bounds());
     Some(predicate.clone_for_update())
 }
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index 694d897d15..10d9cec313 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -84,7 +84,7 @@ pub(crate) fn replace_derive_with_manual_impl(
         add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?;
     }
     if no_traits_found {
-        let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name)));
+        let trait_path = make::ext::ident_path(trait_name);
         add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?;
     }
     Some(())
@@ -159,10 +159,8 @@ fn impl_def_from_trait(
     if trait_items.is_empty() {
         return None;
     }
-    let impl_def = make::impl_trait(
-        trait_path.clone(),
-        make::path_unqualified(make::path_segment(make::name_ref(&annotated_name.text()))),
-    );
+    let impl_def =
+        make::impl_trait(trait_path.clone(), make::ext::ident_path(&annotated_name.text()));
     let (impl_def, first_assoc_item) =
         add_trait_assoc_items_to_impl(sema, trait_items, trait_, impl_def, target_scope);
     Some((impl_def, first_assoc_item))
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
index be7e724b56..f811234c07 100644
--- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
@@ -53,7 +53,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
             let with_placeholder: ast::Pat = match happy_variant {
                 None => make::wildcard_pat().into(),
                 Some(var_name) => make::tuple_struct_pat(
-                    make::path_unqualified(make::path_segment(make::name_ref(var_name))),
+                    make::ext::ident_path(var_name),
                     once(make::wildcard_pat().into()),
                 )
                 .into(),
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
index a986a6ae89..0fec961b43 100644
--- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
@@ -32,7 +32,7 @@ use ide_db::ty_filter::TryEnum;
 // fn main() {
 //     let x: Result<i32, i32> = Result::Ok(92);
 //     let y = match x {
-//         Ok(a) => a,
+//         Ok(it) => it,
 //         $0_ => unreachable!(),
 //     };
 // }
@@ -52,16 +52,17 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
         "Replace unwrap with match",
         target,
         |builder| {
-            let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
-            let it = make::ident_pat(make::name("a")).into();
+            let ok_path = make::ext::ident_path(happy_variant);
+            let it = make::ident_pat(make::name("it")).into();
             let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
 
-            let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
+            let bind_path = make::ext::ident_path("it");
             let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path));
 
-            let unreachable_call = make::expr_unreachable();
-            let err_arm =
-                make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call);
+            let err_arm = make::match_arm(
+                iter::once(make::wildcard_pat().into()),
+                make::ext::expr_unreachable(),
+            );
 
             let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
             let match_expr = make::expr_match(caller.clone(), match_arm_list)
@@ -110,7 +111,7 @@ fn i<T>(a: T) -> T { a }
 fn main() {
     let x: Result<i32, i32> = Result::Ok(92);
     let y = match i(x) {
-        Ok(a) => a,
+        Ok(it) => it,
         $0_ => unreachable!(),
     };
 }
@@ -136,7 +137,7 @@ fn i<T>(a: T) -> T { a }
 fn main() {
     let x = Option::Some(92);
     let y = match i(x) {
-        Some(a) => a,
+        Some(it) => it,
         $0_ => unreachable!(),
     };
 }
@@ -162,7 +163,7 @@ fn i<T>(a: T) -> T { a }
 fn main() {
     let x: Result<i32, i32> = Result::Ok(92);
     let y = match i(x) {
-        Ok(a) => a,
+        Ok(it) => it,
         $0_ => unreachable!(),
     }.count_zeroes();
 }
diff --git a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
index e838630eaa..2f1da82c7d 100644
--- a/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
+++ b/crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
@@ -54,9 +54,7 @@ pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext)
 
             for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
                 let ok_wrapped = make::expr_call(
-                    make::expr_path(make::path_unqualified(make::path_segment(make::name_ref(
-                        "Ok",
-                    )))),
+                    make::expr_path(make::ext::ident_path("Ok")),
                     make::arg_list(iter::once(ret_expr_arg.clone())),
                 );
                 builder.replace_ast(ret_expr_arg, ok_wrapped);
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs
index 5a90ad715b..0dcf20c618 100644
--- a/crates/ide_assists/src/utils.rs
+++ b/crates/ide_assists/src/utils.rs
@@ -159,8 +159,8 @@ pub fn add_trait_assoc_items_to_impl(
         match fn_def.body() {
             Some(_) => fn_def,
             None => {
-                let body =
-                    make::block_expr(None, Some(make::expr_todo())).indent(edit::IndentLevel(1));
+                let body = make::block_expr(None, Some(make::ext::expr_todo()))
+                    .indent(edit::IndentLevel(1));
                 fn_def.with_body(body)
             }
         }
diff --git a/crates/ide_db/src/helpers/merge_imports.rs b/crates/ide_db/src/helpers/merge_imports.rs
index 3f5bbef7fb..1482972792 100644
--- a/crates/ide_db/src/helpers/merge_imports.rs
+++ b/crates/ide_db/src/helpers/merge_imports.rs
@@ -137,7 +137,7 @@ fn recursive_merge(
                             None,
                             false,
                         );
-                        use_trees.insert(idx, make::glob_use_tree());
+                        use_trees.insert(idx, make::use_tree_glob());
                         continue;
                     }
 
diff --git a/crates/ide_db/src/ty_filter.rs b/crates/ide_db/src/ty_filter.rs
index 988ecd0607..00678bf3e9 100644
--- a/crates/ide_db/src/ty_filter.rs
+++ b/crates/ide_db/src/ty_filter.rs
@@ -43,7 +43,7 @@ impl TryEnum {
     pub fn sad_pattern(self) -> ast::Pat {
         match self {
             TryEnum::Result => make::tuple_struct_pat(
-                make::path_unqualified(make::path_segment(make::name_ref("Err"))),
+                make::ext::ident_path("Err"),
                 iter::once(make::wildcard_pat().into()),
             )
             .into(),
@@ -54,12 +54,12 @@ impl TryEnum {
     pub fn happy_pattern(self) -> ast::Pat {
         match self {
             TryEnum::Result => make::tuple_struct_pat(
-                make::path_unqualified(make::path_segment(make::name_ref("Ok"))),
+                make::ext::ident_path("Ok"),
                 iter::once(make::wildcard_pat().into()),
             )
             .into(),
             TryEnum::Option => make::tuple_struct_pat(
-                make::path_unqualified(make::path_segment(make::name_ref("Some"))),
+                make::ext::ident_path("Some"),
                 iter::once(make::wildcard_pat().into()),
             )
             .into(),
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c39e248ce6..a378b1d375 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -3,7 +3,7 @@
 //!
 //! Note that all functions here intended to be stupid constructors, which just
 //! assemble a finish node from immediate children. If you want to do something
-//! smarter than that, it probably doesn't belong in this module.
+//! smarter than that, it belongs to the `ext` submodule.
 //!
 //! Keep in mind that `from_text` functions should be kept private. The public
 //! API should require to assemble every node piecewise. The trick of
@@ -14,13 +14,49 @@ use stdx::{format_to, never};
 
 use crate::{ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, SyntaxToken};
 
+/// While the parent module defines basic atomic "constructors", the `ext`
+/// module defines shortcuts for common things.
+///
+/// It's named `ext` rather than `shortcuts` just to keep it short.
+pub mod ext {
+    use super::*;
+
+    pub fn ident_path(ident: &str) -> ast::Path {
+        path_unqualified(path_segment(name_ref(ident)))
+    }
+
+    pub fn expr_unreachable() -> ast::Expr {
+        expr_from_text("unreachable!()")
+    }
+    pub fn expr_todo() -> ast::Expr {
+        expr_from_text("todo!()")
+    }
+
+    pub fn ty_bool() -> ast::Type {
+        ty_path(ident_path("bool"))
+    }
+    pub fn ty_option(t: ast::Type) -> ast::Type {
+        ty_from_text(&format!("Option<{}>", t))
+    }
+    pub fn ty_result(t: ast::Type, e: ast::Type) -> ast::Type {
+        ty_from_text(&format!("Result<{}, {}>", t, e))
+    }
+}
+
 pub fn name(text: &str) -> ast::Name {
     ast_from_text(&format!("mod {}{};", raw_ident_esc(text), text))
 }
-
 pub fn name_ref(text: &str) -> ast::NameRef {
     ast_from_text(&format!("fn f() {{ {}{}; }}", raw_ident_esc(text), text))
 }
+fn raw_ident_esc(ident: &str) -> &'static str {
+    let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
+    if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
+        "r#"
+    } else {
+        ""
+    }
+}
 
 pub fn lifetime(text: &str) -> ast::Lifetime {
     let mut text = text;
@@ -32,15 +68,6 @@ pub fn lifetime(text: &str) -> ast::Lifetime {
     ast_from_text(&format!("fn f<{}>() {{ }}", text))
 }
 
-fn raw_ident_esc(ident: &str) -> &'static str {
-    let is_keyword = parser::SyntaxKind::from_keyword(ident).is_some();
-    if is_keyword && !matches!(ident, "self" | "crate" | "super" | "Self") {
-        "r#"
-    } else {
-        ""
-    }
-}
-
 // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
 // `expr_xxx`.
 pub fn ty(text: &str) -> ast::Type {
@@ -49,9 +76,6 @@ pub fn ty(text: &str) -> ast::Type {
 pub fn ty_unit() -> ast::Type {
     ty_from_text("()")
 }
-pub fn ty_bool() -> ast::Type {
-    ty_path(path_unqualified(path_segment(name_ref("bool"))))
-}
 pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
     let mut count: usize = 0;
     let mut contents = types.into_iter().inspect(|_| count += 1).join(", ");
@@ -61,11 +85,6 @@ pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
 
     ty_from_text(&format!("({})", contents))
 }
-// FIXME: handle path to type
-pub fn ty_generic(name: ast::NameRef, types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
-    let contents = types.into_iter().join(", ");
-    ty_from_text(&format!("{}<{}>", name, contents))
-}
 pub fn ty_ref(target: ast::Type, exclusive: bool) -> ast::Type {
     ty_from_text(&if exclusive { format!("&mut {}", target) } else { format!("&{}", target) })
 }
@@ -107,7 +126,7 @@ pub fn path_unqualified(segment: ast::PathSegment) -> ast::Path {
 pub fn path_qualified(qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
     ast_from_text(&format!("{}::{}", qual, segment))
 }
-
+// FIXME: path concatenation operation doesn't make sense as AST op.
 pub fn path_concat(first: ast::Path, second: ast::Path) -> ast::Path {
     ast_from_text(&format!("{}::{}", first, second))
 }
@@ -123,15 +142,14 @@ pub fn path_from_segments(
         format!("use {};", segments)
     })
 }
-
+// FIXME: should not be pub
 pub fn path_from_text(text: &str) -> ast::Path {
     ast_from_text(&format!("fn main() {{ let test = {}; }}", text))
 }
 
-pub fn glob_use_tree() -> ast::UseTree {
+pub fn use_tree_glob() -> ast::UseTree {
     ast_from_text("use *;")
 }
-
 pub fn use_tree(
     path: ast::Path,
     use_tree_list: Option<ast::UseTreeList>,
@@ -226,15 +244,6 @@ pub fn expr_literal(text: &str) -> ast::Literal {
 pub fn expr_empty_block() -> ast::Expr {
     expr_from_text("{}")
 }
-pub fn expr_unimplemented() -> ast::Expr {
-    expr_from_text("unimplemented!()")
-}
-pub fn expr_unreachable() -> ast::Expr {
-    expr_from_text("unreachable!()")
-}
-pub fn expr_todo() -> ast::Expr {
-    expr_from_text("todo!()")
-}
 pub fn expr_path(path: ast::Path) -> ast::Expr {
     expr_from_text(&path.to_string())
 }
@@ -463,17 +472,6 @@ pub fn expr_stmt(expr: ast::Expr) -> ast::ExprStmt {
     ast_from_text(&format!("fn f() {{ {}{} (); }}", expr, semi))
 }
 
-pub fn token(kind: SyntaxKind) -> SyntaxToken {
-    tokens::SOURCE_FILE
-        .tree()
-        .syntax()
-        .clone_for_update()
-        .descendants_with_tokens()
-        .filter_map(|it| it.into_token())
-        .find(|it| it.kind() == kind)
-        .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
-}
-
 pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param {
     ast_from_text(&format!("fn f({}: {}) {{ }}", pat, ty))
 }
@@ -611,6 +609,17 @@ fn unroot(n: SyntaxNode) -> SyntaxNode {
     SyntaxNode::new_root(n.green().into())
 }
 
+pub fn token(kind: SyntaxKind) -> SyntaxToken {
+    tokens::SOURCE_FILE
+        .tree()
+        .syntax()
+        .clone_for_update()
+        .descendants_with_tokens()
+        .filter_map(|it| it.into_token())
+        .find(|it| it.kind() == kind)
+        .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
+}
+
 pub mod tokens {
     use once_cell::sync::Lazy;
 


Test patch:
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs
index d884a6eb49..227ecd162f 100644
--- a/crates/hir_def/src/nameres/tests/incremental.rs
+++ b/crates/hir_def/src/nameres/tests/incremental.rs
@@ -137,9 +137,6 @@ m!(Z);
         });
         let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
         assert_eq!(n_recalculated_item_trees, 6);
-        let n_reparsed_macros =
-            events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
-        assert_eq!(n_reparsed_macros, 3);
     }
 
     let new_text = r#"
@@ -158,8 +155,5 @@ m!(Z);
         });
         let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
         assert_eq!(n_recalculated_item_trees, 1);
-        let n_reparsed_macros =
-            events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
-        assert_eq!(n_reparsed_macros, 0);
     }
 }
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 59bcef8fb0..49c1a97760 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -1531,7 +1531,7 @@ enum Result<T, E> { Ok(T), Err(E) }
 fn main() {
     let x: Result<i32, i32> = Result::Ok(92);
     let y = match x {
-        Ok(a) => a,
+        Ok(it) => it,
         $0_ => unreachable!(),
     };
 }