6150: Move ModPath->ast::Path function to IDE layer r=matklad a=matklad

bors r+
🤖

Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
bors[bot] 2020-10-06 14:21:05 +00:00 committed by GitHub
commit 81d6816f17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 65 additions and 46 deletions

View file

@ -1,13 +1,14 @@
//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined. //! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
use rustc_hash::FxHashMap;
use hir::{HirDisplay, PathResolution, SemanticsScope}; use hir::{HirDisplay, PathResolution, SemanticsScope};
use rustc_hash::FxHashMap;
use syntax::{ use syntax::{
algo::SyntaxRewriter, algo::SyntaxRewriter,
ast::{self, AstNode}, ast::{self, AstNode},
SyntaxNode, SyntaxNode,
}; };
use crate::utils::mod_path_to_ast;
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
SyntaxRewriter::from_fn(|element| match element { SyntaxRewriter::from_fn(|element| match element {
syntax::SyntaxElement::Node(n) => { syntax::SyntaxElement::Node(n) => {
@ -189,7 +190,7 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
match resolution { match resolution {
PathResolution::Def(def) => { PathResolution::Def(def) => {
let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?; let found_path = from.find_use_path(self.source_scope.db.upcast(), def)?;
let mut path = path_to_ast(found_path); let mut path = mod_path_to_ast(&found_path);
let type_args = p let type_args = p
.segment() .segment()
@ -210,13 +211,3 @@ impl<'a> AstTransform<'a> for QualifyPaths<'a> {
} }
} }
} }
pub(crate) fn path_to_ast(path: hir::ModPath) -> ast::Path {
let parse = ast::SourceFile::parse(&path.to_string());
parse
.tree()
.syntax()
.descendants()
.find_map(ast::Path::cast)
.unwrap_or_else(|| panic!("failed to parse path {:?}, `{}`", path, path))
}

View file

@ -820,4 +820,29 @@ impl Tr for () {
}"#, }"#,
) )
} }
#[test]
fn weird_path() {
check_assist(
add_missing_impl_members,
r#"
trait Test {
fn foo(&self, x: crate)
}
impl Test for () {
<|>
}
"#,
r#"
trait Test {
fn foo(&self, x: crate)
}
impl Test for () {
fn foo(&self, x: crate) {
${0:todo!()}
}
}
"#,
)
}
} }

View file

@ -13,7 +13,10 @@ use syntax::{
SyntaxNode, SyntaxNode,
}; };
use crate::{utils::insert_use, AssistContext, AssistId, AssistKind, Assists, GroupLabel}; use crate::{
utils::insert_use, utils::mod_path_to_ast, AssistContext, AssistId, AssistKind, Assists,
GroupLabel,
};
// Assist: auto_import // Assist: auto_import
// //
@ -54,7 +57,7 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
range, range,
|builder| { |builder| {
let new_syntax = let new_syntax =
insert_use(&scope, import.to_ast_path(), ctx.config.insert_use.merge); insert_use(&scope, mod_path_to_ast(&import), ctx.config.insert_use.merge);
builder.replace(syntax.text_range(), new_syntax.to_string()) builder.replace(syntax.text_range(), new_syntax.to_string())
}, },
); );

View file

@ -10,9 +10,10 @@ use syntax::{
}; };
use crate::{ use crate::{
assist_context::AssistBuilder, utils::insert_use, AssistContext, AssistId, AssistKind, Assists, assist_context::AssistBuilder,
utils::{insert_use, mod_path_to_ast, ImportScope},
AssistContext, AssistId, AssistKind, Assists,
}; };
use insert_use::ImportScope;
// Assist: extract_struct_from_enum_variant // Assist: extract_struct_from_enum_variant
// //
@ -111,7 +112,8 @@ fn insert_import(
let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?; let scope = ImportScope::find_insert_use_container(path.syntax(), ctx)?;
let syntax = scope.as_syntax_node(); let syntax = scope.as_syntax_node();
let new_syntax = insert_use(&scope, mod_path.to_ast_path(), ctx.config.insert_use.merge); let new_syntax =
insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use.merge);
// FIXME: this will currently panic as multiple imports will have overlapping text ranges // FIXME: this will currently panic as multiple imports will have overlapping text ranges
builder.replace(syntax.text_range(), new_syntax.to_string()) builder.replace(syntax.text_range(), new_syntax.to_string())
} }

View file

@ -7,7 +7,7 @@ use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
use test_utils::mark; use test_utils::mark;
use crate::{ use crate::{
utils::{render_snippet, Cursor, FamousDefs}, utils::{mod_path_to_ast, render_snippet, Cursor, FamousDefs},
AssistContext, AssistId, AssistKind, Assists, AssistContext, AssistId, AssistKind, Assists,
}; };
@ -192,7 +192,7 @@ fn resolve_tuple_of_enum_def(
} }
fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> { fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> {
let path = crate::ast_transform::path_to_ast(module.find_use_path(db, ModuleDef::from(var))?); let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
let pat: ast::Pat = match var.source(db).value.kind() { let pat: ast::Pat = match var.source(db).value.kind() {

View file

@ -19,6 +19,27 @@ use crate::assist_config::SnippetCap;
pub use insert_use::MergeBehaviour; pub use insert_use::MergeBehaviour;
pub(crate) use insert_use::{insert_use, ImportScope}; pub(crate) use insert_use::{insert_use, ImportScope};
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
let mut segments = Vec::new();
let mut is_abs = false;
match path.kind {
hir::PathKind::Plain => {}
hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
segments.push(make::path_segment_crate())
}
hir::PathKind::Abs => is_abs = true,
}
segments.extend(
path.segments
.iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
);
make::path_from_segments(segments, is_abs)
}
pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
extract_trivial_expression(&block) extract_trivial_expression(&block)
.filter(|expr| !expr.syntax().text().contains_char('\n')) .filter(|expr| !expr.syntax().text().contains_char('\n'))

View file

@ -51,7 +51,7 @@ pub use hir_def::{
find_path::PrefixKind, find_path::PrefixKind,
item_scope::ItemInNs, item_scope::ItemInNs,
nameres::ModuleSource, nameres::ModuleSource,
path::ModPath, path::{ModPath, PathKind},
type_ref::{Mutability, TypeRef}, type_ref::{Mutability, TypeRef},
}; };
pub use hir_expand::{ pub use hir_expand::{
@ -63,7 +63,4 @@ pub use hir_ty::display::HirDisplay;
// These are negative re-exports: pub using these names is forbidden, they // These are negative re-exports: pub using these names is forbidden, they
// should remain private to hir internals. // should remain private to hir internals.
#[allow(unused)] #[allow(unused)]
use { use {hir_def::path::Path, hir_expand::hygiene::Hygiene};
hir_def::path::{Path, PathKind},
hir_expand::hygiene::Hygiene,
};

View file

@ -13,7 +13,7 @@ use hir_expand::{
hygiene::Hygiene, hygiene::Hygiene,
name::{AsName, Name}, name::{AsName, Name},
}; };
use syntax::ast::{self, make}; use syntax::ast::{self};
use crate::{ use crate::{
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef},
@ -100,26 +100,6 @@ impl ModPath {
} }
self.segments.first() self.segments.first()
} }
pub fn to_ast_path(&self) -> ast::Path {
let mut segments = Vec::new();
let mut is_abs = false;
match self.kind {
PathKind::Plain => {}
PathKind::Super(0) => segments.push(make::path_segment_self()),
PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
PathKind::Crate => segments.push(make::path_segment_crate()),
PathKind::Abs => is_abs = true,
PathKind::DollarCrate(_) => (),
}
segments.extend(
self.segments
.iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
);
make::path_from_segments(segments, is_abs)
}
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]